Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Payment: Attendance Approval Flow #2097

Open
wants to merge 115 commits into
base: console
Choose a base branch
from

Conversation

rachana-egov
Copy link
Contributor

@rachana-egov rachana-egov commented Jan 3, 2025

Choose the appropriate template for your PR:

Feature PR

Feature Request

JIRA ID

Module

Description

Related Issues


Bugfix PR

Bugfix Request

JIRA ID

Module

Description

Root Cause

Related Issues


Release PR

Summary by CodeRabbit

Based on the comprehensive summary of changes, here are the updated release notes:

  • New Features

    • Added a new Payments module with enhanced functionality for health-related payments.
    • Introduced advanced search and filtering capabilities for bills and attendance.
    • Implemented breadcrumb navigation and custom inbox components.
    • Added support for project and boundary selection.
  • Components Added

    • Developed new UI components for bill management, attendance tracking, and project selection, including BreadCrumbs, CustomBillInbox, MyBillsSearch, DateRangePicker, AlertPopUp, ApproveCommentPopUp, CustomInboxSearchComposer, BillSearchBox, BillBoundaryFilter, BillInboxTable, CustomInboxTable, BoundaryComponent, CustomFilter, CustomSearchComponent, and CustomInboxSearchLinks.
    • Implemented responsive and interactive user interfaces.
  • Hooks and Services

    • Added custom hooks for project search, payments initialization, and attendance boundary searches, including useProjectSearch, usePaymentsInitialization, useAttendanceBoundarySearch, and useAttendanceBoundaryRegisterSearch.
    • Introduced new services for handling project and attendance-related API interactions, including AttendanceService and ProjectService.
  • Improvements

    • Enhanced routing capabilities with new private routes.
    • Improved state management using React hooks.
    • Added internationalization support.
    • Implemented robust error handling.

rachana-egov and others added 30 commits December 19, 2024 09:50
#2065)

HCMPRE-1717:: Load and store project details on Payments module initialization
attendance inbox in  progress
* attendance inbox in  progress

* composer in progress

* inboxserach composer replaced with custom inbox component
* attendance inbox in  progress

* composer in progress

* inboxserach composer replaced with custom inbox component

* boundary service API integration implemented for inbox screen

* Update filter_section.js

---------

Co-authored-by: rachana-egov <[email protected]>
* attendance inbox in  progress

* composer in progress

* inboxserach composer replaced with custom inbox component

* boundary service API integration implemented for inbox screen

* check box and register search API integration in progress
* attendance inbox in  progress

* composer in progress

* inboxserach composer replaced with custom inbox component

* boundary service API integration implemented for inbox screen

* check box and register search API integration in progress

* table data enriched
* attendance inbox in  progress

* composer in progress

* inboxserach composer replaced with custom inbox component

* boundary service API integration implemented for inbox screen

* check box and register search API integration in progress

* table data enriched

* removed debugger

* variable name changed
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 9

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a65ff03 and 2d20a68.

📒 Files selected for processing (3)
  • health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/bill_inbox/bill_boundary_filter.js (1 hunks)
  • health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/ViewAttendance.js (2 hunks)
  • health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/my_bills.js (1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/bill_inbox/bill_boundary_filter.js (1)

Pattern **/*.js: check

health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/ViewAttendance.js (1)

Pattern **/*.js: check

health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/my_bills.js (1)

Pattern **/*.js: check

🪛 Biome (1.9.4)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/bill_inbox/bill_boundary_filter.js

[error] 71-81: Enforce to have the onClick mouse event with the onKeyUp, the onKeyDown, or the onKeyPress keyboard event.

Actions triggered using mouse events should have corresponding keyboard events to account for keyboard-only navigation.

(lint/a11y/useKeyWithClickEvents)


[error] 86-86: Enforce to have the onClick mouse event with the onKeyUp, the onKeyDown, or the onKeyPress keyboard event.

Actions triggered using mouse events should have corresponding keyboard events to account for keyboard-only navigation.

(lint/a11y/useKeyWithClickEvents)


[error] 87-87: Alternative text title element cannot be empty

For accessibility purposes, SVGs should have an alternative text, provided via title element. If the svg element has role="img", you should add the aria-label or aria-labelledby attribute.

(lint/a11y/noSvgWithoutTitle)

health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/ViewAttendance.js

[error] 47-47: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


[error] 88-88: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


[error] 107-107: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


[error] 282-282: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


[error] 307-309: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


[error] 482-492: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)


[error] 494-506: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)


[error] 508-537: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)

health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/my_bills.js

[error] 36-36: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)

🔇 Additional comments (19)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/my_bills.js (2)

1-8: Consider consolidating component imports.

Components are being imported from two similarly named packages: @egovernments/digit-ui-react-components and @egovernments/digit-ui-components. Consider consolidating imports from a single package or document the reason for using two separate packages.


43-50: Fix effect dependencies and consolidate storage cleanup.

The effect is missing its dependencies array and the storage cleanup could be consolidated.

health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/ViewAttendance.js (9)

47-47: Simplify boolean expression

Use the truthiness of registerNumber directly instead of a ternary operator.

Apply this diff:

- enabled: registerNumber ? true : false,
+ enabled: !!registerNumber,
🧰 Tools
🪛 Biome (1.9.4)

[error] 47-47: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


88-88: Simplify boolean expression

Use AttendanceData directly rather than using a ternary operator.

Apply this diff:

- enabled: ((AttendanceData ? true : false) && disabledAction && data?.[0]?.musterRollStatus !== "APPROVED") || triggerEstimate,
+ enabled: (AttendanceData && disabledAction && data?.[0]?.musterRollStatus !== "APPROVED") || triggerEstimate,
🧰 Tools
🪛 Biome (1.9.4)

[error] 88-88: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


107-107: Simplify boolean expression

Rely on AttendanceData as a boolean indicator without a ternary operator.

Apply this diff:

- enabled: (AttendanceData ? true : false) && !disabledAction,
+ enabled: AttendanceData && !disabledAction,
🧰 Tools
🪛 Biome (1.9.4)

[error] 107-107: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


282-282: Simplify boolean expression

Use a concise truthy check for individualIds.length instead of a ternary operator.

Apply this diff:

- enabled: individualIds.length > 0 ? true : false,
+ enabled: !!individualIds.length,
🧰 Tools
🪛 Biome (1.9.4)

[error] 282-282: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


391-393: Return the loader component to display it

The <LoaderWithGap /> component inside the if block is not returned or rendered, so it won't display as intended.

Apply this diff to ensure the loader is displayed:

- if (updateMutation.isLoading) {
-   <LoaderWithGap />
- }
+ if (updateMutation.isLoading) {
+   return <LoaderWithGap />;
+ }

217-223: Avoid using setTimeout for navigation after showing toast

Using setTimeout to delay navigation can lead to unpredictable behavior if the UI experiences lag. Instead, use the onClose callback of the toast to ensure navigation occurs after the toast is dismissed.

Apply this diff:

- setShowToast({ key: "success", label: t("HCM_AM_ATTENDANCE_UPDATED_SUCCESSFULLY"), transitionTime: 3000 });
- // Delay the navigation for 3 seconds
- setTimeout(() => {
-   setUpdateDisabled(false);
-   history.push(`/${window.contextPath}/employee/payments/view-attendance?registerNumber=${registerNumber}&boundaryCode=${boundaryCode}`);
- }, 3000);
+ setShowToast({ 
+   key: "success", 
+   label: t("HCM_AM_ATTENDANCE_UPDATED_SUCCESSFULLY"), 
+   transitionTime: 3000,
+   onClose: () => {
+     setUpdateDisabled(false);
+     history.push(`/${window.contextPath}/employee/payments/view-attendance?registerNumber=${registerNumber}&boundaryCode=${boundaryCode}`);
+   },
+ });

226-228: Handle possible undefined error messages

Ensure that you have a default message in case error?.response?.data?.Errors is undefined or empty to prevent displaying undefined messages to the user.

Apply this diff:

- setShowToast({ key: "error", label: t(error?.response?.data?.Errors?.[0]?.message), transitionTime: 3000 });
+ const errorMessage = error?.response?.data?.Errors?.[0]?.message || t("COMMON_ERROR_MESSAGE");
+ setShowToast({ key: "error", label: errorMessage, transitionTime: 3000 });

508-537: Add a unique key prop for each child in the array

When rendering an array of elements in actionFields, each element should have a unique key prop to help React identify them.

Apply this diff to add key properties:

            actionFields={[
-             disabledAction ? (
+             disabledAction ? (
+               <Button
+                 key="goBackButton"
                  label={t(`HCM_AM_GO_BACK`)}
                  /* ...other props */
                />
              ) : editAttendance ? (
+               <Button
+                 key="submitButton"
                  /* ...other props */
                />
              ) : (
+               <Button
+                 key="actionsButton"
                  /* ...other props */
                />
              ),
            ]}
🧰 Tools
🪛 Biome (1.9.4)

[error] 508-537: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)


341-346: 🧹 Nitpick (assertive)

Remove unnecessary comments or address TODOs

The comment /// need to update dependency may be outdated or unnecessary. Ensure that all comments are relevant, and remove any that are not needed.

Consider removing the comment if the dependencies are correctly set:

- }, [AllIndividualsData, data]); /// need to update dependency
+ }, [AllIndividualsData, data]);

Likely invalid or redundant comment.

health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/bill_inbox/bill_boundary_filter.js (8)

3-3: Remove unused import CheckBox

The CheckBox component is imported but not used in this file. Removing it will clean up the code.

Apply this diff to remove the unused import:

- import { CheckBox, SubmitBar } from "@egovernments/digit-ui-components";
+ import { SubmitBar } from "@egovernments/digit-ui-components";

71-81: Enhance accessibility by adding keyboard event handlers

The <div> element with an onClick handler should support keyboard interactions for accessibility. Please add onKeyPress and tabIndex={0} to enable keyboard navigation for keyboard-only users.

Apply this diff:

  <div
    onClick={handleClearFilter}
+   onKeyPress={(e) => { if (e.key === 'Enter') handleClearFilter(); }}
+   tabIndex={0}
    style={{
🧰 Tools
🪛 Biome (1.9.4)

[error] 71-81: Enforce to have the onClick mouse event with the onKeyUp, the onKeyDown, or the onKeyPress keyboard event.

Actions triggered using mouse events should have corresponding keyboard events to account for keyboard-only navigation.

(lint/a11y/useKeyWithClickEvents)


86-86: Improve accessibility of the clickable <span> element

The <span> element with an onClick handler should support keyboard interactions and have appropriate accessibility attributes. Consider changing it to a <button> or adding tabIndex={0} and onKeyPress to enable keyboard navigation.

For example, change it to a <button>:

- <span onClick={() => { }} style={{ border: "1px solid #E0E0E0", padding: "6px", marginBottom: "10px" }}>
+ <button
+   onClick={() => { }}
+   style={{ border: "1px solid #E0E0E0", padding: "6px", marginBottom: "10px" }}
+   aria-label={t('Refresh')}
+ >
🧰 Tools
🪛 Biome (1.9.4)

[error] 86-86: Enforce to have the onClick mouse event with the onKeyUp, the onKeyDown, or the onKeyPress keyboard event.

Actions triggered using mouse events should have corresponding keyboard events to account for keyboard-only navigation.

(lint/a11y/useKeyWithClickEvents)


87-92: Provide accessibility attributes for SVG

Include role="img" and an aria-label or a <title> element in the SVG for screen readers to improve accessibility.

Update the SVG element as follows:

<svg
  width="17"
  height="17"
  viewBox="0 0 16 22"
  fill="none"
  xmlns="http://www.w3.org/2000/svg"
+ role="img"
+ aria-label={t("HCM_REFRESH_ICON")}
>

Alternatively, add a <title> element inside the SVG:

<svg
  width="17"
  height="17"
  viewBox="0 0 16 22"
  fill="none"
  xmlns="http://www.w3.org/2000/svg"
>
+ <title>{t("HCM_REFRESH_ICON")}</title>
  <path
    ...
  />
</svg>
🧰 Tools
🪛 Biome (1.9.4)

[error] 87-87: Alternative text title element cannot be empty

For accessibility purposes, SVGs should have an alternative text, provided via title element. If the svg element has role="img", you should add the aria-label or aria-labelledby attribute.

(lint/a11y/noSvgWithoutTitle)


95-106: Remove commented-out code

There is a block of commented-out code which should be removed to improve code cleanliness and maintainability. If this code might be needed later, you can retrieve it from version control.


36-44: Include updateBoundaryFilters in the dependency array

The useEffect hook uses updateBoundaryFilters, but it is not included in the dependency array. This could lead to unexpected behavior if updateBoundaryFilters changes without triggering the effect.

Update the dependency array as follows:

-    }, [levelSelected])
+    }, [levelSelected, updateBoundaryFilters])

116-116: Fix the spelling of updateSeeeionStorage prop

There's a typo in the prop name updateSeeeionStorage. It should be updateSessionStorage to ensure consistency and prevent confusion.

Apply this diff to correct the spelling:

-            updateSeeeionStorage={(newSelectedValues) => {
+            updateSessionStorage={(newSelectedValues) => {

10-10: 🧹 Nitpick (assertive)

Remove unused state variable boundaryType

The boundaryType state variable is declared but never updated or effectively used in the code. Since boundaryType is not utilized, consider removing it to simplify the code.

Apply this diff to remove boundaryType:

-    const [boundaryType, setBoundaryType] = useState("");

Likely invalid or redundant comment.

Comment on lines +14 to +20
const [tableData, setTableData] = useState([]);
const [billID, setBillID] = useState(null);
const [dateRange, setDateRange] = useState({
startDate: '',
endDate: '',
title: '',
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Consider using TypeScript or PropTypes for better type safety.

The component uses multiple state variables without type definitions. This could lead to type-related bugs, especially when handling dates and complex objects.

Consider:

  1. Migrating to TypeScript, or
  2. Adding PropTypes for runtime type checking:
MyBills.propTypes = {
  tableData: PropTypes.arrayOf(PropTypes.array).isRequired,
  dateRange: PropTypes.shape({
    startDate: PropTypes.string,
    endDate: PropTypes.string,
    title: PropTypes.string
  }).isRequired
};

Comment on lines 79 to 84
const reportDetails = individualEntry?.additionalDetails?.reportDetails || {
"status": "FAILED", // INITIATED, COMPLETED, FAILED
"pdfReportId": "d5a504fb-ebb8-41be-afa0-24b4f1bd575b",
"excelReportId": "de5f2b24-b60d-4d1f-b550-56abe1dabb2f",
"errorMessage": "HCM_AM_BILL_REPORT_GENERATION_FAILED"
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Remove hardcoded report IDs from the code.

The hardcoded report IDs in the fallback object could pose a security risk if they're actual UUIDs from your system.

Consider:

  1. Using placeholder IDs for development
  2. Moving these values to environment configuration
  3. Generating new IDs for each report
 const reportDetails = individualEntry?.additionalDetails?.reportDetails || {
     "status": "FAILED",
-    "pdfReportId": "d5a504fb-ebb8-41be-afa0-24b4f1bd575b",
-    "excelReportId": "de5f2b24-b60d-4d1f-b550-56abe1dabb2f",
+    "pdfReportId": "",
+    "excelReportId": "",
     "errorMessage": "HCM_AM_BILL_REPORT_GENERATION_FAILED"
 };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const reportDetails = individualEntry?.additionalDetails?.reportDetails || {
"status": "FAILED", // INITIATED, COMPLETED, FAILED
"pdfReportId": "d5a504fb-ebb8-41be-afa0-24b4f1bd575b",
"excelReportId": "de5f2b24-b60d-4d1f-b550-56abe1dabb2f",
"errorMessage": "HCM_AM_BILL_REPORT_GENERATION_FAILED"
};
const reportDetails = individualEntry?.additionalDetails?.reportDetails || {
"status": "FAILED", // INITIATED, COMPLETED, FAILED
"pdfReportId": "",
"excelReportId": "",
"errorMessage": "HCM_AM_BILL_REPORT_GENERATION_FAILED"
};

Comment on lines 116 to 127
return (
<React.Fragment>
<Header styles={{ fontSize: "32px" }}>
{t("HCM_AM_MY_BILLS")}
</Header>


<MyBillsSearch onSubmit={onSubmit} onClear={onClear} />

<Card>
{isFetching ? <Loader /> : tableData.length === 0 ? <NoResultsFound text={t(`HCM_AM_NO_DATA_FOUND_FOR_BILLS`)} /> : <MyBillsTable data={tableData} />}
</Card>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Improve accessibility of the bills table.

The table component lacks proper ARIA attributes for screen readers.

Add appropriate ARIA labels and roles:

 <Card>
-    {isFetching ? <Loader /> : tableData.length === 0 ? <NoResultsFound text={t(`HCM_AM_NO_DATA_FOUND_FOR_BILLS`)} /> : <MyBillsTable data={tableData} />}
+    <div role="region" aria-label={t("HCM_AM_MY_BILLS")}>
+        {isFetching ? (
+            <Loader aria-label={t("LOADING")} />
+        ) : tableData.length === 0 ? (
+            <NoResultsFound text={t(`HCM_AM_NO_DATA_FOUND_FOR_BILLS`)} role="alert" />
+        ) : (
+            <MyBillsTable data={tableData} aria-label={t("HCM_AM_BILLS_TABLE")} />
+        )}
+    </div>
 </Card>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
return (
<React.Fragment>
<Header styles={{ fontSize: "32px" }}>
{t("HCM_AM_MY_BILLS")}
</Header>
<MyBillsSearch onSubmit={onSubmit} onClear={onClear} />
<Card>
{isFetching ? <Loader /> : tableData.length === 0 ? <NoResultsFound text={t(`HCM_AM_NO_DATA_FOUND_FOR_BILLS`)} /> : <MyBillsTable data={tableData} />}
</Card>
return (
<React.Fragment>
<Header styles={{ fontSize: "32px" }}>
{t("HCM_AM_MY_BILLS")}
</Header>
<MyBillsSearch onSubmit={onSubmit} onClear={onClear} />
<Card>
<div role="region" aria-label={t("HCM_AM_MY_BILLS")}>
{isFetching ? (
<Loader aria-label={t("LOADING")} />
) : tableData.length === 0 ? (
<NoResultsFound text={t(`HCM_AM_NO_DATA_FOUND_FOR_BILLS`)} role="alert" />
) : (
<MyBillsTable data={tableData} aria-label={t("HCM_AM_BILLS_TABLE")} />
)}
</div>
</Card>

Comment on lines 24 to 41
const BillSearchCri = {
url: `/health-expense/bill/v1/_search`,
body: {
billCriteria: {
tenantId: tenantId,
localityCode: project?.address?.boundary,
referenceIds: [project?.[0]?.id],
...(billID ? { billNumbers: [billID] } : {}),
...(dateRange.startDate && dateRange.endDate ? { fromDate: new Date(dateRange.startDate).getTime(), toDate: new Date(dateRange.endDate).getTime() } : {})
}
},
config: {
enabled: project ? true : false,
select: (data) => {
return data;
},
},
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Improve API configuration robustness.

Several improvements needed in the search criteria configuration:

  1. The boolean expression can be simplified
  2. The API configuration lacks error handling

Apply these improvements:

 const BillSearchCri = {
     url: `/health-expense/bill/v1/_search`,
     body: {
         billCriteria: {
             tenantId: tenantId,
-            localityCode: project?.address?.boundary,
+            localityCode: project?.address?.boundary ?? null,
             referenceIds: [project?.[0]?.id],
             ...(billID ? { billNumbers: [billID] } : {}),
             ...(dateRange.startDate && dateRange.endDate ? { fromDate: new Date(dateRange.startDate).getTime(), toDate: new Date(dateRange.endDate).getTime() } : {})
         }
     },
     config: {
-        enabled: project ? true : false,
+        enabled: Boolean(project),
         select: (data) => {
-            return data;
+            if (!data?.bills) {
+                throw new Error('Invalid response format');
+            }
+            return data;
         },
+        onError: (error) => {
+            console.error('Bill search failed:', error);
+            // Consider showing a user-friendly error message
+        }
     },
 };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const BillSearchCri = {
url: `/health-expense/bill/v1/_search`,
body: {
billCriteria: {
tenantId: tenantId,
localityCode: project?.address?.boundary,
referenceIds: [project?.[0]?.id],
...(billID ? { billNumbers: [billID] } : {}),
...(dateRange.startDate && dateRange.endDate ? { fromDate: new Date(dateRange.startDate).getTime(), toDate: new Date(dateRange.endDate).getTime() } : {})
}
},
config: {
enabled: project ? true : false,
select: (data) => {
return data;
},
},
};
const BillSearchCri = {
url: `/health-expense/bill/v1/_search`,
body: {
billCriteria: {
tenantId: tenantId,
localityCode: project?.address?.boundary ?? null,
referenceIds: [project?.[0]?.id],
...(billID ? { billNumbers: [billID] } : {}),
...(dateRange.startDate && dateRange.endDate ? { fromDate: new Date(dateRange.startDate).getTime(), toDate: new Date(dateRange.endDate).getTime() } : {})
}
},
config: {
enabled: Boolean(project),
select: (data) => {
if (!data?.bills) {
throw new Error('Invalid response format');
}
return data;
},
onError: (error) => {
console.error('Bill search failed:', error);
// Consider showing a user-friendly error message
}
},
};
🧰 Tools
🪛 Biome (1.9.4)

[error] 36-36: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)

const location = useLocation();
const { t } = useTranslation();
const history = useHistory();
const { registerNumber, boundaryCode } = Digit.Hooks.useQueryParams();
const { fromCampaignSupervisor } = location.state || false;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Ensure safe access to location.state

Destructuring fromCampaignSupervisor from location.state || false can cause issues if location.state is null or not an object. Consider providing a default object to prevent errors.

Apply this diff to fix the issue:

- const { fromCampaignSupervisor } = location.state || false;
+ const { fromCampaignSupervisor } = location.state || {};

Alternatively, use optional chaining:

const fromCampaignSupervisor = location.state?.fromCampaignSupervisor || false;

Comment on lines +307 to +309
enabled: AttendanceData?.attendanceRegister[0]?.staff?.find(
(staff) => staff?.staffType?.includes("OWNER")
)?.userId ? true : false,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Simplify boolean expression

Simplify the condition by removing the unnecessary ternary operator.

Apply this diff:

- enabled: AttendanceData?.attendanceRegister[0]?.staff?.find(
-   (staff) => staff?.staffType?.includes("OWNER")
- )?.userId ? true : false,
+ enabled: !!AttendanceData?.attendanceRegister[0]?.staff?.find(
+   (staff) => staff?.staffType?.includes("OWNER")
+ )?.userId,
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
enabled: AttendanceData?.attendanceRegister[0]?.staff?.find(
(staff) => staff?.staffType?.includes("OWNER")
)?.userId ? true : false,
enabled: !!AttendanceData?.attendanceRegister[0]?.staff?.find(
(staff) => staff?.staffType?.includes("OWNER")
)?.userId,
🧰 Tools
🪛 Biome (1.9.4)

[error] 307-309: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)

Comment on lines +345 to +346
setAttendanceSummary(getUserAttendanceSummary(data, AllIndividualsData, t));
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Address the pending dependency update

The comment /// need to update dependency indicates that there might be a missing dependency in the useEffect hook. Ensure all necessary dependencies are included to prevent potential bugs.

Review the dependencies for the useEffect hook and include any missing ones. For example, if t is a dependency, update the hook:

- }, [AllIndividualsData, data]); /// need to update dependency
+ }, [AllIndividualsData, data, t]); // Updated dependencies

Committable suggestion skipped: line range outside the PR's diff.


const handleClearFilter = () => {
setResetFilters(true);
setBoundary(""); // Clear the boundary value
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Ensure consistent reset of boundary state

In handleClearFilter, the boundary state is reset using setBoundary(""), whereas in other parts of the code setBoundary(null) is used (e.g., lines 31 and 41). This inconsistency might lead to unexpected behavior. Consider using null consistently to represent an unset boundary.

Apply this diff to standardize the reset value:

-        setBoundary(""); // Clear the boundary value
+        setBoundary(null); // Clear the boundary value
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
setBoundary(""); // Clear the boundary value
setBoundary(null); // Clear the boundary value

makeReset={() => {
setResetFilters(false);
}}
initialValue={sessionStorage.getItem("selectedValues")}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codebase verification

Standardize session storage access using Digit.SessionStorage

The codebase shows a clear preference for using the Digit.SessionStorage abstraction. Update the code to maintain consistency:

-            initialValue={sessionStorage.getItem("selectedValues")}
+            initialValue={Digit.SessionStorage.get("selectedValues")}
🔗 Analysis chain

Standardize the use of session storage

At line 115, sessionStorage.getItem("selectedValues") is used, whereas elsewhere in the code Digit.SessionStorage is used (e.g., lines 8, 13, 28). For consistency and to prevent potential issues, consider using Digit.SessionStorage throughout the code if it is the preferred abstraction.

Update the code as follows:

-            initialValue={sessionStorage.getItem("selectedValues")}
+            initialValue={Digit.SessionStorage.get("selectedValues")}
🏁 Scripts executed

The following scripts were executed for the analysis:

Error: No shell scripts found


Script:

#!/bin/bash
# Search for Digit.SessionStorage usage patterns
ast-grep --pattern 'Digit.SessionStorage.$_($_)'

# Search for direct sessionStorage usage
ast-grep --pattern 'sessionStorage.$_($_)'

# Backup search with ripgrep for both patterns
echo "=== Searching for Digit.SessionStorage usage ==="
rg "Digit\.SessionStorage\." -A 1 -B 1

echo "=== Searching for direct sessionStorage usage ==="
rg "sessionStorage\." -A 1 -B 1

Length of output: 66141

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 12

♻️ Duplicate comments (2)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/MyBillsSearch.js (1)

62-62: 🧹 Nitpick (assertive)

Use proper translation function in DateRangePicker.

Passing a simple identity function to the t prop may lead to missing translations. Use the actual t function from useTranslation().

Apply this change:

- t={(key) => key}
+ t={t}
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/my_bills.js (1)

36-36: 🧹 Nitpick (assertive)

Simplify boolean expression for enabled config.

The expression enabled: project ? true : false can be simplified by converting project to a boolean.

Apply this change:

- enabled: project ? true : false,
+ enabled: Boolean(project),
🧰 Tools
🪛 Biome (1.9.4)

[error] 36-36: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2d20a68 and 12b115b.

📒 Files selected for processing (6)
  • health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/DateRangePicker.js (1 hunks)
  • health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/MyBillsSearch.js (1 hunks)
  • health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/MyBillsTable.js (1 hunks)
  • health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/bill_inbox/BillInbox.js (1 hunks)
  • health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/ViewAttendance.js (2 hunks)
  • health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/my_bills.js (1 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/ViewAttendance.js (1)

Pattern **/*.js: check

health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/my_bills.js (1)

Pattern **/*.js: check

health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/MyBillsSearch.js (1)

Pattern **/*.js: check

health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/bill_inbox/BillInbox.js (1)

Pattern **/*.js: check

health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/MyBillsTable.js (1)

Pattern **/*.js: check

health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/DateRangePicker.js (1)

Pattern **/*.js: check

🪛 Biome (1.9.4)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/ViewAttendance.js

[error] 47-47: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


[error] 85-85: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


[error] 104-104: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


[error] 279-279: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


[error] 304-306: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


[error] 479-489: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)


[error] 491-503: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)


[error] 505-534: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)

health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/my_bills.js

[error] 36-36: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)

health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/MyBillsSearch.js

[error] 49-49: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead

(lint/style/useSelfClosingElements)


[error] 71-76: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead

(lint/style/useSelfClosingElements)


[error] 73-73: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)


[error] 74-74: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)

health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/bill_inbox/BillInbox.js

[error] 48-48: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


[error] 51-51: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


[error] 68-68: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


[error] 186-194: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead

(lint/style/useSelfClosingElements)


[error] 197-198: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead

(lint/style/useSelfClosingElements)


[error] 211-217: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead

(lint/style/useSelfClosingElements)


[error] 254-263: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead

(lint/style/useSelfClosingElements)


[error] 273-285: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)


[error] 296-312: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)

health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/MyBillsTable.js

[error] 13-13: Template literals are preferred over string concatenation.

Unsafe fix: Use a template literal.

(lint/style/useTemplate)


[error] 47-47: Template literals are preferred over string concatenation.

Unsafe fix: Use a template literal.

(lint/style/useTemplate)


[error] 140-140: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


[error] 134-172: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)


[error] 173-173: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)

health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/DateRangePicker.js

[error] 197-197: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead

(lint/style/useSelfClosingElements)


[error] 128-128: This let declares a variable that is only assigned once.

'noOfDays' is never reassigned.

Safe fix: Use const instead.

(lint/style/useConst)

🔇 Additional comments (36)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/bill_inbox/BillInbox.js (10)

1-1: Remove unused and invalid imports

The imports useReducer, useMemo, and use are not used in this file. Additionally, use is not a valid React hook and may have been included by mistake. Please remove these to clean up the code.


5-5: Define location or use useLocation hook

The variable location is used but not defined in this scope. If you intend to access the browser's location or the route's state, consider importing useLocation from react-router-dom and using it to retrieve the location object.


23-23: Remove commented-out code

The commented-out line is unnecessary and can be removed to keep the code clean.


48-48: Simplify boolean expressions

The use of ternary operators returning boolean literals can be simplified by directly assigning the condition's result. This improves code readability.

Apply these changes:

At line 48:

- isChildrenRequired: selectedLevel != null && selectedLevel?.code === "DISTRICT" ? true : false,
+ isChildrenRequired: selectedLevel != null && selectedLevel?.code === "DISTRICT",

At line 51:

- enabled: selectedBoundaryCode && selectedProject ? true : false,
+ enabled: !!(selectedBoundaryCode && selectedProject),

At line 68:

- enabled: selectedBoundaryCode ? true : false,
+ enabled: !!selectedBoundaryCode,

Also applies to: 51-51, 68-68

🧰 Tools
🪛 Biome (1.9.4)

[error] 48-48: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


186-194: Use a self-closing tag for <CustomInboxSearchLinks>

JSX elements without child content should be self-closing.

Apply this change:

<CustomInboxSearchLinks
    headerText={"HCM_AM_BILL_INBOX"}
    links={[
        {
            url: "/employee/payments/my-bills",
            text: "HCM_AM_MY_BILLS",
        },
    ]}
- ></CustomInboxSearchLinks>
+ />
🧰 Tools
🪛 Biome (1.9.4)

[error] 186-194: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead

(lint/style/useSelfClosingElements)


197-198: Use a self-closing tag for <BillSearchBox>

When a JSX element has no child content, prefer using a self-closing tag.

Apply this change:

<BillSearchBox
    onLevelSelect={handleSearchChange}
    initialProject={selectedProject}
    initialAggregationLevel={selectedLevel}
- ></BillSearchBox>
+ />
🧰 Tools
🪛 Biome (1.9.4)

[error] 197-198: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead

(lint/style/useSelfClosingElements)


211-217: Use a self-closing tag for <BillBoundaryFilter>

Prefer a self-closing tag for elements without children.

Apply this change:

<BillBoundaryFilter
    isRequired={ScreenTypeEnum.BILL}
    selectedProject={selectedProject}
    selectedLevel={selectedLevel}
    onFilterChange={handleFilterUpdate}
    updateBoundaryFilters={updateFilters}
- ></BillBoundaryFilter>
+ />
🧰 Tools
🪛 Biome (1.9.4)

[error] 211-217: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead

(lint/style/useSelfClosingElements)


254-263: Use a self-closing tag for <BillInboxTable>

JSX elements without child content should be self-closing.

Apply this change:

<Card>
  <BillInboxTable
      isFetching={isFetching}
      tableData={tableData}
      currentPage={currentPage}
      rowsPerPage={rowsPerPage}
      handlePageChange={handlePageChange}
      handlePerRowsChange={handlePerRowsChange}
      totalCount={totalCount}
      status={activeLink.code}
-   ></BillInboxTable>
+   />
</Card>
🧰 Tools
🪛 Biome (1.9.4)

[error] 254-263: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead

(lint/style/useSelfClosingElements)


273-285: Add a key property when returning elements in an array

Even if you only return a single element in an array, React recommends specifying a unique key to maintain stable identity across renders.

Apply these changes:

At lines 273-285:

actionFields={[
+  <Button
+    key="generate-bill-btn"
     icon="CheckCircle"
     label={t(`HCM_AM_GENERATE_BILL_LABEL`)}
     onClick={() => {
         triggerGenerateBill();
     }}
     style={{
         minWidth: "14rem",
     }}
     type="button"
     variation="primary"
     isDisabled={generateBillMutation.isLoading}
  />,
]}

At lines 296-312:

actionFields={[
+  <Button
+    key="generate-bill-btn-conditional"
     icon="CheckCircle"
     label={t(`HCM_AM_GENERATE_BILL_LABEL`)}
     onClick={() => {
         !showGenerateBillAction || BillData?.bills?.length >= 0
             ? setShowToast({ key: "info", label: t("HCM_AM_GENERATE_BILLS_CANNOT_BE_CALLED_INFO_MESSAGE"), transitionTime: 3000 })
             : triggerGenerateBill();
     }}
     style={{
         minWidth: "14rem",
         cursor: !showGenerateBillAction || BillData?.bills?.length >= 0 ? "not-allowed" : "pointer",
         opacity: !showGenerateBillAction || BillData?.bills?.length >= 0 ? 0.5 : 1,
     }}
     type="button"
     variation="primary"
     isDisabled={generateBillMutation.isLoading}
/>,
]}

Also applies to: 296-312

🧰 Tools
🪛 Biome (1.9.4)

[error] 273-285: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)


300-308: Logical error in the onClick handler condition

The condition BillData?.bills?.length >= 0 will always be true because an array's length is always 0 or greater. This means triggerGenerateBill() will never be called.

Consider revising the condition to correctly reflect the intended logic. If you intend to check if there are no bills, you might use:

!showGenerateBillAction || BillData?.bills?.length > 0

This ensures that triggerGenerateBill() is called when there are no bills.

health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/ViewAttendance.js (14)

16-16: Ensure safe access to location.state

Destructuring fromCampaignSupervisor from location.state || false can cause issues if location.state is null or not an object. Consider providing a default object to prevent errors.

Apply this diff:

- const { fromCampaignSupervisor } = location.state || false;
+ const { fromCampaignSupervisor } = location.state || {};

47-47: Simplify boolean expression

Simplify the condition by removing the unnecessary ternary operator.

Apply this diff:

- enabled: registerNumber ? true : false,
+ enabled: !!registerNumber,
🧰 Tools
🪛 Biome (1.9.4)

[error] 47-47: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


85-85: Simplify boolean expression

Simplify the condition by removing the unnecessary ternary operator.

Apply this diff:

- enabled: ((AttendanceData ? true : false) && disabledAction && AttendanceData?.attendanceRegister?.[0]?.reviewStatus !== "APPROVED") || triggerEstimate,
+ enabled: (AttendanceData && disabledAction && AttendanceData?.attendanceRegister?.[0]?.reviewStatus !== "APPROVED") || triggerEstimate,
🧰 Tools
🪛 Biome (1.9.4)

[error] 85-85: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


104-104: Simplify boolean expression

Simplify the condition by removing the unnecessary ternary operator.

Apply this diff:

- enabled: (AttendanceData ? true : false) && (!disabledAction || AttendanceData?.attendanceRegister?.[0]?.reviewStatus === "APPROVED"),
+ enabled: AttendanceData && (!disabledAction || AttendanceData?.attendanceRegister?.[0]?.reviewStatus === "APPROVED"),
🧰 Tools
🪛 Biome (1.9.4)

[error] 104-104: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


279-279: Simplify boolean expression

Simplify the condition by removing the unnecessary ternary operator.

Apply this diff:

- enabled: individualIds.length > 0 ? true : false,
+ enabled: !!individualIds.length,
🧰 Tools
🪛 Biome (1.9.4)

[error] 279-279: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


304-306: Simplify boolean expression

Simplify the condition by removing the unnecessary ternary operator.

Apply this diff:

- enabled: AttendanceData?.attendanceRegister[0]?.staff?.find(
-   (staff) => staff?.staffType?.includes("OWNER")
- )?.userId ? true : false,
+ enabled: !!AttendanceData?.attendanceRegister[0]?.staff?.find(
+   (staff) => staff?.staffType?.includes("OWNER")
+ )?.userId,
🧰 Tools
🪛 Biome (1.9.4)

[error] 304-306: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


315-336: Handle cases where matchingIndividual may be undefined

In the getUserAttendanceSummary function, ensure that you handle cases where matchingIndividual is undefined to avoid potential runtime errors.

Consider updating the else block to use the individualId if available:

- return ["N/A", "Unknown", "N/A", "Unassigned", individualEntry?.modifiedTotalAttendance || individualEntry.actualTotalAttendance || 0];
+ return [individualEntry.individualId || "N/A", "Unknown", "N/A", "Unassigned", individualEntry?.modifiedTotalAttendance || individualEntry.actualTotalAttendance || 0];

345-345: Update dependencies in useEffect hook

The comment /// need to update dependency indicates missing dependencies in the useEffect hook. Ensure all necessary dependencies are included to prevent potential bugs.

Review and update the dependency array as needed.


388-390: Ensure the loader component is returned to display correctly

The <LoaderWithGap /> component inside the if block is not returned or rendered, so it won't display as intended.

Apply this diff:

- if (updateMutation.isLoading) {
-   <LoaderWithGap />
- }
+ if (updateMutation.isLoading) {
+   return <LoaderWithGap />;
+ }

479-489: Add a unique key prop to each element in actionFields

When rendering elements in arrays, each element should have a unique key prop to help React identify them.

Apply this diff:

disabledAction ? (
+  <Button
+    key="goBackButton"
     label={t(`HCM_AM_GO_BACK`)}
     title={t(`HCM_AM_GO_BACK`)}
     onClick={() => {
       fromCampaignSupervisor
         ? history.push(`/${window.contextPath}/employee/payments/generate-bill`, { fromViewScreen: true })
         : history.push(`/${window.contextPath}/employee/payments/registers-inbox`);
     }}
     type="button"
     style={{ minWidth: "14rem" }}
     variation="primary"
   />
) : ...
🧰 Tools
🪛 Biome (1.9.4)

[error] 479-489: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)


491-503: Add a unique key prop to each element in actionFields

When rendering elements in arrays, each element should have a unique key prop to help React identify them.

Apply this diff:

) : editAttendance ? (
+  <Button
+    key="submitButton"
     icon="CheckCircle"
     label={t(`HCM_AM_SUBMIT_LABEL`)}
     title={t(`HCM_AM_SUBMIT_LABEL`)}
     onClick={() => {
       setUpdateDisabled(true);
       triggerMusterRollUpdate();
     }}
     style={{ minWidth: "14rem" }}
     type="button"
     variation="primary"
     isDisabled={updateMutation.isLoading || updateDisabled || !isSubmitEnabled}
   />
) : ...
🧰 Tools
🪛 Biome (1.9.4)

[error] 491-503: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)


505-534: Add a unique key prop to each element in actionFields

When rendering elements in arrays, each element should have a unique key prop to help React identify them.

Apply this diff:

) : (
+  <Button
+    key="actionsButton"
     className="custom-class"
     iconFill=""
     label={t(`HCM_AM_ACTIONS`)}
     menuStyles={{
       bottom: "40px",
     }}
     onOptionSelect={(value) => {
       if (value.code === "EDIT_ATTENDANCE") {
         setOpenEditAlertPopUp(true);
       } else if (value.code === "APPROVE") {
         setOpenApproveCommentPopUp(true);
       }
     }}
     options={[
       {
         code: "EDIT_ATTENDANCE",
         name: t(`HCM_AM_ACTIONS_EDIT_ATTENDANCE`),
       },
       {
         code: "APPROVE",
         name: t(`HCM_AM_ACTIONS_APPROVE`),
       },
     ]}
     optionsKey="name"
     size=""
     style={{ minWidth: "14rem" }}
     title=""
     type="actionButton"
   />
)
🧰 Tools
🪛 Biome (1.9.4)

[error] 505-534: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)


215-221: Avoid using setTimeout for navigation after showing toast

Using setTimeout to delay navigation can lead to unpredictable behavior. Consider using a callback or promise resolution to navigate after the toast has been displayed.

Apply this diff:

setShowToast({
  key: "success",
  label: t("HCM_AM_ATTENDANCE_UPDATED_SUCCESSFULLY"),
  transitionTime: 3000,
+ onClose: () => {
+   setUpdateDisabled(false);
+   history.push(`/${window.contextPath}/employee/payments/view-attendance?registerNumber=${registerNumber}&boundaryCode=${boundaryCode}`);
+ },
});
- // Delay the navigation for 3 seconds
- setTimeout(() => {
-   setUpdateDisabled(false);
-   history.push(`/${window.contextPath}/employee/payments/view-attendance?registerNumber=${registerNumber}&boundaryCode=${boundaryCode}`);
- }, 3000);

224-225: Ensure a default error message is displayed

When handling errors, ensure that a default message is shown if error?.response?.data?.Errors is undefined or empty to prevent displaying undefined to the user.

Apply this diff:

onError: (error) => {
  setUpdateDisabled(false);
- setShowToast({ key: "error", label: t(error?.response?.data?.Errors?.[0]?.message), transitionTime: 3000 });
+ const errorMessage = error?.response?.data?.Errors?.[0]?.message || t("COMMON_ERROR_MESSAGE");
+ setShowToast({ key: "error", label: errorMessage, transitionTime: 3000 });
}
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/MyBillsTable.js (3)

140-140: 🧹 Nitpick (assertive)

Simplify boolean expression in showBottom prop.

The expression showBottom={isLastRow ? false : true} can be simplified by negating isLastRow, which enhances code clarity.

Apply this change:

- showBottom={isLastRow ? false : true}
+ showBottom={!isLastRow}

Likely invalid or redundant comment.

🧰 Tools
🪛 Biome (1.9.4)

[error] 140-140: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


77-81: 🧹 Nitpick (assertive)

Destructure props instead of using spread operator.

Destructuring specific props improves readability and makes it explicit which props are being used.

Apply this change:

- const MyBillsTable = ({ ...props }) => {
+ const MyBillsTable = ({ data, handlePageChange, handlePerRowsChange, onRowSelect }) => {

Update all instances of props within the component to use the destructured variables.

Likely invalid or redundant comment.


225-237: 🧹 Nitpick (assertive)

Remove unnecessary placeholder functions.

The onFilter, onSelectedRowsChange, and customSortFunction props have placeholder functions that are not implemented. Consider removing them or providing actual implementations to clean up the code.

Apply these changes:

- onFilter={function noRefCheck() { }}
+ onFilter={null}
- selection={{
-     addCheckbox: false,
-     checkboxLabel: "",
-     initialSelectedRows: [],
-     onSelectedRowsChange: function noRefCheck() { },
-     showSelectedState: false,
- }}
+ selection={{
+     addCheckbox: false,
+     checkboxLabel: "",
+     initialSelectedRows: [],
+     onSelectedRowsChange: null,
+     showSelectedState: false,
+ }}
- sorting={{
-     customSortFunction: function noRefCheck() { },
-     initialSortOrder: "",
-     isTableSortable: false,
- }}
+ sorting={{
+     customSortFunction: null,
+     initialSortOrder: "",
+     isTableSortable: false,
+ }}

Likely invalid or redundant comment.

health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/MyBillsSearch.js (3)

18-18: Avoid using state as a key prop.

Using state variables as keys in components like DateRangePicker can lead to unintended behavior. Instead, consider controlling re-renders through props or using a different approach.


49-49: 🧹 Nitpick (assertive)

Use self-closing tag for <TextBlock> component.

Since <TextBlock> has no children, it can be self-closed to improve code readability.

Apply this change:

- <TextBlock body={`${t("HCM_AM_BILL_ID")}`}></TextBlock>
+ <TextBlock body={`${t("HCM_AM_BILL_ID")}`} />

Likely invalid or redundant comment.

🧰 Tools
🪛 Biome (1.9.4)

[error] 49-49: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead

(lint/style/useSelfClosingElements)


71-76: 🧹 Nitpick (assertive)

Add key props to buttons in ButtonGroup.

Each child in an array should have a unique key prop to help React identify which items have changed.

Apply these changes:

<ButtonGroup
  buttonsArray={[
    <Button
+     key="clear-button"
      variation="teritiary"
      label={t(`HCM_AM_CLEAR`)}
      type="button"
      onClick={handleClear}
      size="large"
    />,
    <Button
+     key="search-button"
      variation="primary"
      label={t(`HCM_AM_SEARCH`)}
      type="button"
      onClick={handleSearch}
      size="large"
    />,
  ]}
/>

Likely invalid or redundant comment.

🧰 Tools
🪛 Biome (1.9.4)

[error] 71-76: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead

(lint/style/useSelfClosingElements)


[error] 73-73: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)


[error] 74-74: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)

health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/my_bills.js (4)

43-49: 🛠️ Refactor suggestion

Add dependency array to useEffect to prevent unnecessary re-renders.

The useEffect hook for cleaning up session storage lacks a dependency array, which can cause it to run on every render.

Add an empty dependency array to ensure it runs only once:

useEffect(() => {
  // Cleanup code
- });
+ }, []);

Likely invalid or redundant comment.


79-84: ⚠️ Potential issue

Remove hardcoded report IDs from reportDetails.

Hardcoding report IDs can lead to security risks and should be avoided. Use placeholder values or fetch them dynamically.

Apply this change:

const reportDetails = individualEntry?.additionalDetails?.reportDetails || {
  "status": "FAILED", // INITIATED, COMPLETED, FAILED
- "pdfReportId": "d5a504fb-ebb8-41be-afa0-24b4f1bd575b",
- "excelReportId": "de5f2b24-b60d-4d1f-b550-56abe1dabb2f",
+ "pdfReportId": "",
+ "excelReportId": "",
  "errorMessage": "HCM_AM_BILL_REPORT_GENERATION_FAILED"
};

Likely invalid or redundant comment.


54-69: 🧹 Nitpick (assertive)

Improve robustness of formatTimestampToDate function.

Enhance the function to handle various input types and invalid dates more gracefully.

Apply these changes:

function formatTimestampToDate(timestamp) {
  if (!timestamp || (typeof timestamp !== "number" && typeof timestamp !== "string")) {
    return t("INVALID_TIMESTAMP");
  }
  const date = new Date(timestamp);
+ if (isNaN(date.getTime())) {
+   return t("INVALID_DATE");
+ }
  // Existing date formatting
}

Likely invalid or redundant comment.


116-127: 🧹 Nitpick (assertive)

Add ARIA attributes for better accessibility.

Enhance the accessibility of your application by adding appropriate ARIA roles and labels to components.

Example:

<Card>
+ <div role="region" aria-label={t("HCM_AM_MY_BILLS")}>
  {isFetching ? (
    <Loader aria-label={t("LOADING")} />
  ) : tableData.length === 0 ? (
    <NoResultsFound text={t(`HCM_AM_NO_DATA_FOUND_FOR_BILLS`)} role="alert" />
  ) : (
    <MyBillsTable data={tableData} aria-label={t("HCM_AM_BILLS_TABLE")} />
  )}
+ </div>
</Card>

Likely invalid or redundant comment.

health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/DateRangePicker.js (2)

1-34: LGTM! Well-structured imports and utility functions.

The imports are well-organized and the utility functions are clear and focused.


197-197: Use self-closing tag for TextBlock component.

🧰 Tools
🪛 Biome (1.9.4)

[error] 197-197: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead

(lint/style/useSelfClosingElements)

const downloadExcel = (blob, fileName) => {
const link = document.createElement("a");
link.href = URL.createObjectURL(blob);
link.download = fileName + ".xlsx";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Use template literals instead of string concatenation.

In lines 13 and 47, you're using string concatenation to construct the download attribute for the link element. Using template literals improves readability and aligns with modern JavaScript best practices.

Apply these changes:

Line 13:

- link.download = fileName + ".xlsx";
+ link.download = `${fileName}.xlsx`;

Line 47:

- link.download = fileName + ".pdf";
+ link.download = `${fileName}.pdf`;

Also applies to: 47-47

🧰 Tools
🪛 Biome (1.9.4)

[error] 13-13: Template literals are preferred over string concatenation.

Unsafe fix: Use a template literal.

(lint/style/useTemplate)

Comment on lines 134 to 172
reportDetails?.status === "COMPLETED" ? <Button
className="custom-class"
iconFill=""
icon="FileDownload"
isSuffix
label={t(`HCM_AM_DOWNLOAD_BILLS`)}
showBottom={isLastRow ? false : true}
onOptionSelect={(value) => {
if (value.code === "HCM_AM_PDF") {
if (reportDetails?.pdfReportId) {
downloadPDFWithName({ fileStoreId: reportDetails?.pdfReportId, customName: `${billId}` })
} else {
setShowToast({ key: "error", label: t(`HCM_AM_PDF_GENERATION_FAILED`), transitionTime: 3000 });
}
} else if (value.code === "HCM_AM_EXCEL") {
if (reportDetails?.excelReportId) {
downloadExcelWithName({ fileStoreId: reportDetails?.excelReportId, customName: `${billId}` });
} else {
setShowToast({ key: "error", label: t(`HCM_AM_EXCEL_GENERATION_FAILED`), transitionTime: 3000 });
}

}
}}
options={[
{
code: "HCM_AM_EXCEL",
name: t(`HCM_AM_EXCEL`),
},
{
code: "HCM_AM_PDF",
name: t(`HCM_AM_PDF`),
},
]}
optionsKey="name"
size=""
style={{ minWidth: "15rem" }}
type="actionButton"
variation="secondary"
/> :
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Add key props to elements in iterables.

When rendering lists in React, each element should have a unique key prop to help React identify which items have changed and manage re-renders efficiently.

Add key props to the elements in the array and JSX elements within the mapped rows.

Example for the array elements in line 127:

return [
  { label: billId, maxLength: 64, key: `billId-${index}` },
  { label: billDate, maxLength: 64, key: `billDate-${index}` },
  // ... other items
];

For the <Button> component in lines 134-172:

- reportDetails?.status === "COMPLETED" ? <Button
+ reportDetails?.status === "COMPLETED" ? <Button
+   key={`download-button-${index}`}
    // ...props
  />

For the <TooltipWrapper> component in lines 173-190:

- <TooltipWrapper
+ <TooltipWrapper
+   key={`tooltip-${index}`}
    // ...props
  >

Also applies to: 173-190

🧰 Tools
🪛 Biome (1.9.4)

[error] 140-140: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


[error] 134-172: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)

Comment on lines 21 to 40
axios
.get("/filestore/v1/files/id", {
responseType: "arraybuffer",
headers: {
"Content-Type": "application/json",
Accept: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
"auth-token": Digit.UserService.getUser()?.["access_token"],
},
params: {
tenantId: Digit.ULBService.getCurrentTenantId(),
fileStoreId: fileStoreId,
},
})
.then(async (res) => {
downloadExcel(
new Blob([res.data], { type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" }),
customName ? customName : "download"
);
});
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Update MIME types and headers in download functions.

In both downloadExcelWithName and downloadPDFWithName, the MIME types and headers are set for Excel files, even in the PDF function. This could cause incorrect file downloads.

Update the MIME types and headers in downloadPDFWithName to match PDF specifications.

Apply these changes in downloadPDFWithName:

Headers (lines 59-62):

headers: {
-   "Content-Type": "application/json",
-   Accept: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
+   "Content-Type": "application/pdf",
+   Accept: "application/pdf",
    "auth-token": Digit.UserService.getUser()?.["access_token"],
},

Blob creation (line 70):

downloadExcel(
-   new Blob([res.data], { type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" }),
+   new Blob([res.data], { type: "application/pdf" }),
    customName ? customName : "download"
);

Also applies to: 55-74

Comment on lines +257 to +265
<Toast
style={{ zIndex: 10001 }}
label={showToast.label}
type={showToast.key}
// error={showToast.key === "error"}
transitionTime={showToast.transitionTime}
onClose={() => setShowToast(null)}
/>
)}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Avoid inline styles for Toast component.

Using inline styles can make the code harder to maintain. Consider using a CSS class or a styled component instead.

Example:

<Toast
-   style={{ zIndex: 10001 }}
    label={showToast.label}
    type={showToast.key}
    transitionTime={showToast.transitionTime}
    onClose={() => setShowToast(null)}
/>

And in your CSS:

.toast-custom {
  z-index: 10001;
}

Then apply the class:

<Toast
  className="toast-custom"
  // ...other props
/>

const history = useHistory();
const url = Digit.Hooks.useQueryParams();
const [showToast, setShowToast] = useState(null);
const tenantId = Digit.ULBService.getCurrentTenantId();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Remove unused state variable showToast if not needed.

If showToast is not being used elsewhere in the code, consider removing it to clean up the state management.

Comment on lines +36 to +242
},
selectedText: {
color: "#ffffff", // White text
},
hoverDay: {
backgroundColor: "#81c784", // Light green on hover
color: "#000000", // Black text on hover
},
};

const handleSelect = (ranges) => {
const { range1: selection } = ranges;
const { startDate, endDate, title, duration } = selection;
setInitialDate((prevState) => ({
...prevState, // Keep the previous values
startDate: startDate, // Update only the `startDate`
}));
if (isStartDateFocused(focusedRange[1])) {
setSelectionRange(selection);
}
if (isEndDateFocused(focusedRange[1])) {
setSelectionRange({ title, duration, startDate, endDate: addSeconds(addMinutes(addHours(endDate, 23), 59), 59) });
setIsModalOpen(false);
}
};

const handleFocusChange = (focusedRange) => {
const [rangeIndex, rangeStep] = focusedRange;
setFocusedRange(focusedRange);
};

const handleClose = () => {
setIsModalOpen(false);
};

function formatDateRange(selectionRange) {
const startDate = new Date(selectionRange.startDate);
const endDate = new Date(selectionRange.endDate);

const format = (date) => {
const day = String(date.getDate()).padStart(2, '0');
const month = String(date.getMonth() + 1).padStart(2, '0'); // Months are 0-indexed
const year = date.getFullYear();
return `${day}/${month}/${year}`;
};

return `${format(startDate)}-${format(endDate)}`;
}


return (
<div className="">
<div className="row border-none date-range-pair">

<TextBlock body={t(`${title}`)}></TextBlock>
<div className="employee-select-wrap attendence-date-picker" style={{ marginBottom: "0" }} ref={wrapperRef}>

<TextInput type="text" className="cursorPointer" onIconSelection={() => {

setIsModalOpen((prevState) => !prevState);
}} onChange={() => { }} populators={{ customIcon: "DateRange" }} value={initialDate.startDate === "" ? null : formatDateRange(selectionRange)}
/>

{isModalOpen && (
<div className="options-card" style={{ overflow: "visible", width: "unset", maxWidth: "fit-content" }}>
<DateRange
className="pickerShadow"
focusedRange={focusedRange}
values={values}
ranges={[selectionRange]}
// rangeColors={["#fbeee8"]}
maxDate={new Date()}
onChange={handleSelect}
onRangeFocusChange={setFocusedRange}
retainEndDateOnFirstSelection={true}
showSelectionPreview={true}
staticRanges={staticRanges}
inputRanges={[]}
// dayContentRenderer={(date) => {
// const isSelected =
// date >= selectionRange.startDate && date <= selectionRange.endDate;
// return (
// <div
// style={{
// ...styles.selectedRange,
// ...(isSelected && styles.selectedText),
// }}
// >
// {date.getDate()}
// </div>
// );
// }}
/>
</div>
)}
</div>
</div>
</div>
);
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Consider performance optimizations for the DateRangePicker component.

While the component is well-structured, consider these architectural improvements:

  1. Memoize callback functions using useCallback
  2. Extract the DateRange modal into a separate component
  3. Consider using a date management library like date-fns-tz for better timezone handling
🧰 Tools
🪛 Biome (1.9.4)

[error] 197-197: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead

(lint/style/useSelfClosingElements)


[error] 128-128: This let declares a variable that is only assigned once.

'noOfDays' is never reassigned.

Safe fix: Use const instead.

(lint/style/useConst)

Comment on lines +221 to +235
// dayContentRenderer={(date) => {
// const isSelected =
// date >= selectionRange.startDate && date <= selectionRange.endDate;
// return (
// <div
// style={{
// ...styles.selectedRange,
// ...(isSelected && styles.selectedText),
// }}
// >
// {date.getDate()}
// </div>
// );
// }}
/>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Remove commented code.

The commented dayContentRenderer code should either be implemented or removed to maintain clean code.

- // dayContentRenderer={(date) => {
-   const isSelected =
-     date >= selectionRange.startDate && date <= selectionRange.endDate;
-   return (
-     <div
-       style={{
-         ...styles.selectedRange,
-         ...(isSelected && styles.selectedText),
-       }}
-     >
-       {date.getDate()}
-     </div>
-   );
- }}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// dayContentRenderer={(date) => {
// const isSelected =
// date >= selectionRange.startDate && date <= selectionRange.endDate;
// return (
// <div
// style={{
// ...styles.selectedRange,
// ...(isSelected && styles.selectedText),
// }}
// >
// {date.getDate()}
// </div>
// );
// }}
/>
/>

Comment on lines +43 to +61
useEffect(() => {
setSelectionRange(
{
startDate: new Date(epochStartDate),
endDate: new Date(epochEndDate)
})
}, [])

useEffect(() => {
const handleClickOutside = (event) => {
if (wrapperRef.current && !wrapperRef.current.contains(event.target)) {
setIsModalOpen(false);
}
};
document.addEventListener("mousedown", handleClickOutside);
return () => {
document.removeEventListener("mousedown", handleClickOutside);
};
}, [wrapperRef]);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Add cleanup for click outside handler.

The click outside handler is properly set up, but consider using a ref for the handler function to prevent unnecessary re-renders.

+ const handleClickOutside = useRef((event) => {
+   if (wrapperRef.current && !wrapperRef.current.contains(event.target)) {
+     setIsModalOpen(false);
+   }
+ }).current;

  useEffect(() => {
-   const handleClickOutside = (event) => {
-     if (wrapperRef.current && !wrapperRef.current.contains(event.target)) {
-       setIsModalOpen(false);
-     }
-   };
-   document.addEventListener("mousedown", handleClickOutside);
+   document.addEventListener("mousedown", handleClickOutside);
    return () => {
      document.removeEventListener("mousedown", handleClickOutside);
    };
- }, [wrapperRef]);
+ }, [handleClickOutside]);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
useEffect(() => {
setSelectionRange(
{
startDate: new Date(epochStartDate),
endDate: new Date(epochEndDate)
})
}, [])
useEffect(() => {
const handleClickOutside = (event) => {
if (wrapperRef.current && !wrapperRef.current.contains(event.target)) {
setIsModalOpen(false);
}
};
document.addEventListener("mousedown", handleClickOutside);
return () => {
document.removeEventListener("mousedown", handleClickOutside);
};
}, [wrapperRef]);
useEffect(() => {
setSelectionRange(
{
startDate: new Date(epochStartDate),
endDate: new Date(epochEndDate)
})
}, [])
const handleClickOutside = useRef((event) => {
if (wrapperRef.current && !wrapperRef.current.contains(event.target)) {
setIsModalOpen(false);
}
}).current;
useEffect(() => {
document.addEventListener("mousedown", handleClickOutside);
return () => {
document.removeEventListener("mousedown", handleClickOutside);
};
}, [handleClickOutside]);

Comment on lines +153 to +167
const handleSelect = (ranges) => {
const { range1: selection } = ranges;
const { startDate, endDate, title, duration } = selection;
setInitialDate((prevState) => ({
...prevState, // Keep the previous values
startDate: startDate, // Update only the `startDate`
}));
if (isStartDateFocused(focusedRange[1])) {
setSelectionRange(selection);
}
if (isEndDateFocused(focusedRange[1])) {
setSelectionRange({ title, duration, startDate, endDate: addSeconds(addMinutes(addHours(endDate, 23), 59), 59) });
setIsModalOpen(false);
}
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Extract time constants and improve error handling.

The handleSelect function uses magic numbers for time manipulation and lacks error handling for invalid dates.

+ const TIME_CONSTANTS = {
+   HOURS_IN_DAY: 23,
+   MINUTES_IN_HOUR: 59,
+   SECONDS_IN_MINUTE: 59
+ };

  const handleSelect = (ranges) => {
+   if (!ranges?.range1) {
+     console.error('Invalid range selection');
+     return;
+   }
    const { range1: selection } = ranges;
    const { startDate, endDate, title, duration } = selection;
+   if (!(startDate instanceof Date) || !(endDate instanceof Date)) {
+     console.error('Invalid date objects');
+     return;
+   }
    setInitialDate((prevState) => ({
      ...prevState,
      startDate: startDate,
    }));
    if (isStartDateFocused(focusedRange[1])) {
      setSelectionRange(selection);
    }
    if (isEndDateFocused(focusedRange[1])) {
      setSelectionRange({ 
        title, 
        duration, 
        startDate, 
-       endDate: addSeconds(addMinutes(addHours(endDate, 23), 59), 59)
+       endDate: addSeconds(
+         addMinutes(
+           addHours(endDate, TIME_CONSTANTS.HOURS_IN_DAY),
+           TIME_CONSTANTS.MINUTES_IN_HOUR
+         ),
+         TIME_CONSTANTS.SECONDS_IN_MINUTE
+       )
      });
      setIsModalOpen(false);
    }
  };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const handleSelect = (ranges) => {
const { range1: selection } = ranges;
const { startDate, endDate, title, duration } = selection;
setInitialDate((prevState) => ({
...prevState, // Keep the previous values
startDate: startDate, // Update only the `startDate`
}));
if (isStartDateFocused(focusedRange[1])) {
setSelectionRange(selection);
}
if (isEndDateFocused(focusedRange[1])) {
setSelectionRange({ title, duration, startDate, endDate: addSeconds(addMinutes(addHours(endDate, 23), 59), 59) });
setIsModalOpen(false);
}
};
const TIME_CONSTANTS = {
HOURS_IN_DAY: 23,
MINUTES_IN_HOUR: 59,
SECONDS_IN_MINUTE: 59
};
const handleSelect = (ranges) => {
if (!ranges?.range1) {
console.error('Invalid range selection');
return;
}
const { range1: selection } = ranges;
const { startDate, endDate, title, duration } = selection;
if (!(startDate instanceof Date) || !(endDate instanceof Date)) {
console.error('Invalid date objects');
return;
}
setInitialDate((prevState) => ({
...prevState,
startDate: startDate,
}));
if (isStartDateFocused(focusedRange[1])) {
setSelectionRange(selection);
}
if (isEndDateFocused(focusedRange[1])) {
setSelectionRange({
title,
duration,
startDate,
endDate: addSeconds(
addMinutes(
addHours(endDate, TIME_CONSTANTS.HOURS_IN_DAY),
TIME_CONSTANTS.MINUTES_IN_HOUR
),
TIME_CONSTANTS.SECONDS_IN_MINUTE
)
});
setIsModalOpen(false);
}
};

Comment on lines +127 to +138
const getDuration = (startDate, endDate) => {
let noOfDays = (new Date(endDate).getTime() - new Date(startDate).getTime()) / (1000 * 3600 * 24);
if (noOfDays > 91) {
return "month";
}
if (noOfDays < 90 && noOfDays >= 14) {
return "week";
}
if (noOfDays <= 14) {
return "day";
}
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Extract magic numbers into named constants.

The getDuration function uses magic numbers which makes the code less maintainable and harder to understand.

+ const DURATION_THRESHOLDS = {
+   QUARTER: 91,  // days in a quarter
+   FORTNIGHT: 14 // two weeks
+ };
+ 
+ const DURATION_TYPES = {
+   MONTH: 'month',
+   WEEK: 'week',
+   DAY: 'day'
+ };

  const getDuration = (startDate, endDate) => {
-   let noOfDays = (new Date(endDate).getTime() - new Date(startDate).getTime()) / (1000 * 3600 * 24);
+   const noOfDays = (new Date(endDate).getTime() - new Date(startDate).getTime()) / (1000 * 3600 * 24);
-   if (noOfDays > 91) {
-     return "month";
+   if (noOfDays > DURATION_THRESHOLDS.QUARTER) {
+     return DURATION_TYPES.MONTH;
    }
-   if (noOfDays < 90 && noOfDays >= 14) {
-     return "week";
+   if (noOfDays < DURATION_THRESHOLDS.QUARTER && noOfDays >= DURATION_THRESHOLDS.FORTNIGHT) {
+     return DURATION_TYPES.WEEK;
    }
-   if (noOfDays <= 14) {
-     return "day";
+   if (noOfDays <= DURATION_THRESHOLDS.FORTNIGHT) {
+     return DURATION_TYPES.DAY;
    }
  };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const getDuration = (startDate, endDate) => {
let noOfDays = (new Date(endDate).getTime() - new Date(startDate).getTime()) / (1000 * 3600 * 24);
if (noOfDays > 91) {
return "month";
}
if (noOfDays < 90 && noOfDays >= 14) {
return "week";
}
if (noOfDays <= 14) {
return "day";
}
};
const DURATION_THRESHOLDS = {
QUARTER: 91, // days in a quarter
FORTNIGHT: 14 // two weeks
};
const DURATION_TYPES = {
MONTH: 'month',
WEEK: 'week',
DAY: 'day'
};
const getDuration = (startDate, endDate) => {
const noOfDays = (new Date(endDate).getTime() - new Date(startDate).getTime()) / (1000 * 3600 * 24);
if (noOfDays > DURATION_THRESHOLDS.QUARTER) {
return DURATION_TYPES.MONTH;
}
if (noOfDays < DURATION_THRESHOLDS.QUARTER && noOfDays >= DURATION_THRESHOLDS.FORTNIGHT) {
return DURATION_TYPES.WEEK;
}
if (noOfDays <= DURATION_THRESHOLDS.FORTNIGHT) {
return DURATION_TYPES.DAY;
}
};
🧰 Tools
🪛 Biome (1.9.4)

[error] 128-128: This let declares a variable that is only assigned once.

'noOfDays' is never reassigned.

Safe fix: Use const instead.

(lint/style/useConst)

* attendance inbox in  progress

* composer in progress

* inboxserach composer replaced with custom inbox component

* boundary service API integration implemented for inbox screen

* check box and register search API integration in progress

* table data enriched

* removed debugger

* variable name changed

* tab section functionlity added

* attendance register param changed

* localization code and table value changed

* inbox pagination and status register count fixed

* table component css style changed

* padding removed from table style

* console removed

* HCMPRE-1774: point-1 project drop down is put in the filter section and search section is not required as per last demo

* fliter boundary dropdown in progress

* staffName key changed for attendance mark by

* bug fixes

* code comment added why not used inboxsearch composer

* boundary service made dynamic

* boundary component made dynamic

* boundary component issue fixed for mandatory filed and drop down reset

* commented code removed

* bug fixes done

* ticket: HCMPRE-1822, boundary option reloaded and error scenation handled for project selection and boundary selection in attendance register inbox

* HCMPRE-1822::table rows per page issue fixed, and digit.session storage implemented
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (28)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/PaymentsCard.js (1)

16-19: ⚠️ Potential issue

Maintain consistent URL pattern across the codebase

The hardcoded /payments-ui/ prefix deviates from the codebase's pattern of using ${window.contextPath}. This could cause routing issues across different environments.

Apply this diff to maintain consistency:

-      link: `/payments-ui/employee/payments/${pathSuffix}`,
+      link: `/${window.contextPath}/employee/payments/${pathSuffix}`,
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/sample.js (9)

6-6: ⚠️ Potential issue

Correct the typo in the prop name updateSeeeionStorage.

The prop updateSeeeionStorage in the BoundaryComponent has a misspelling. It should be updateSessionStorage to match the intended functionality and maintain consistency.

Apply this diff to fix the typo:

-const BoundaryComponent = ({ reset, makeReset, initialValue, updateSeeeionStorage, selectedProject, onChange, lowestLevel, isRequired }) => {
+const BoundaryComponent = ({ reset, makeReset, initialValue, updateSessionStorage, selectedProject, onChange, lowestLevel, isRequired }) => {

7-7: ⚠️ Potential issue

Add null check before accessing boundaryHierarchyOrder.

The variable kk directly accesses map on Digit.SessionStorage.get("boundaryHierarchyOrder") without checking if it's null or undefined. This can cause runtime errors if boundaryHierarchyOrder is not set.

Apply this diff to add a null check:

-  const kk = Digit.SessionStorage.get("boundaryHierarchyOrder").map((item) => item.code);
+  const boundaryHierarchyOrder = Digit.SessionStorage.get("boundaryHierarchyOrder") || [];
+  const kk = boundaryHierarchyOrder.map((item) => item.code);

7-7: 🧹 Nitpick (assertive)

Rename variable kk for better readability.

The variable name kk is not descriptive. Renaming it to something like boundaryHierarchyCodes improves code readability and maintainability.

Apply this diff:

-  const kk = Digit.SessionStorage.get("boundaryHierarchyOrder").map((item) => item.code);
+  const boundaryHierarchyCodes = Digit.SessionStorage.get("boundaryHierarchyOrder").map((item) => item.code);

32-32: 🧹 Nitpick (assertive)

Clarify the usage of lowest vs. lowestLevel.

Both lowest and lowestLevel seem to represent similar concepts. Consider consolidating them or renaming to avoid confusion.


105-115: ⚠️ Potential issue

Add null checks before accessing nested properties in childrenData.

When accessing childrenData[0]?.boundary[0].boundaryType, there's a risk of undefined if boundary or its first element does not exist. This can cause runtime errors.

Apply this diff to ensure safe access:

-    if (childrenData && childrenData.length > 0) {
+    if (childrenData?.length > 0 && childrenData[0]?.boundary?.length > 0 && childrenData[0]?.boundary[0]?.boundaryType) {
       setValue((prevState) => ({
         ...prevState,
         [childrenData[0]?.boundary[0].boundaryType]: [childrenData[0]?.boundary[0]],
       }));

       const formattedData = createFormattedData(childrenData[0]?.boundary[0].boundaryType);
       setBoundaryData(formattedData);
     }

216-216: 🧹 Nitpick (assertive)

⚠️ Potential issue

Simplify the boolean expression for isRequired.

The ternary operations with true and false are unnecessary and can be simplified for clarity.

Apply this diff:

-                    isRequired={isRequired == ScreenTypeEnum.BILL ? true : key == "DISTRICT" ? true : false}
+                    isRequired={isRequired === ScreenTypeEnum.BILL || key === "DISTRICT"}

This removes redundant ternary checks and makes the condition more readable.

🧰 Tools
🪛 Biome (1.9.4)

[error] 216-216: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


248-248: 🧹 Nitpick (assertive)

Simplify the condition in TextBlock component.

The check isRequired == true can be simplified to just isRequired.

Apply this diff:

-          <TextBlock body={isRequired == true ? `${t(label)}*` : t(label)} />
+          <TextBlock body={isRequired ? `${t(label)}*` : t(label)} />

34-47: 🧹 Nitpick (assertive)

Remove commented-out code to clean up the file.

Large blocks of commented-out code can clutter the file and should be removed if not needed.

Apply this diff to remove the commented code:

-  // useEffect(() => {
-  //   debugger;
-  //   if (initialValue) {
-  //     setSelectedValues(JSON.parse(initialValue));
-  //     const data = JSON.parse(initialValue);
-  //     const updatedValues = kk.reduce((acc, boundary) => {
-  //       acc[boundary] = data[boundary] ? [data[boundary]] : [];
-  //       return acc;
-  //     }, {});
-
-  //     debugger;
-  //     setValue(updatedValues);
-  //   }
-  // }, []);

88-104: 🧹 Nitpick (assertive)

Remove unused commented-out useEffect block.

The code from lines 88 to 104 is commented out and should be removed if it's no longer needed to keep the codebase clean.

Apply this diff:

-  // useEffect(() => {
-  //   if (selectedProject) {
-  //     setSelectedValues(defaultSelectData);
-  //     setValue(
-  //       kk.reduce((acc, curr) => {
-  //         acc[curr] = [];
-  //         return acc;
-  //       }, {})
-  //     );
-  //     setBoundaryData(defaultBoundaryData);
-  //   }
-
-  //   // if (updateSeeeionStorage) {
-  //   //   updateSeeeionStorage(defaultSelectData);
-  //   // }
-  // }, [selectedProject]);
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/custom_comp/filter_section.js (8)

4-4: 🧹 Nitpick (assertive)

Rename the import path for BoundaryComponent for clarity.

The import path "../sample" is non-descriptive and could be confusing. Consider renaming the file to something more meaningful like "../BoundaryComponent" or updating the import statement to reflect the component's purpose.

Apply this diff:

-import BoundaryComponent from "../sample";
+import BoundaryComponent from "../BoundaryComponent";

41-41: 🧹 Nitpick (assertive)

Use const instead of let for datak.

Since datak is not reassigned, it should be declared with const to prevent accidental reassignment.

Apply this diff:

-      let datak =
+      const datak =
        Digit?.SessionStorage.get("staffProjects") || ...
🧰 Tools
🪛 Biome (1.9.4)

[error] 41-41: This let declares a variable that is only assigned once.

'datak' is never reassigned.

Safe fix: Use const instead.

(lint/style/useConst)


98-104: ⚠️ Potential issue

Provide descriptive text for the SVG icon for accessibility.

The SVG lacks alternative text, making it inaccessible to screen readers. Add an aria-label or <title> to convey its purpose.

Apply this diff:

             <svg
               width="17"
               height="17"
               viewBox="0 0 16 22"
               fill="none"
+              aria-label="Refresh icon"
               xmlns="http://www.w3.org/2000/svg"
             >
🧰 Tools
🪛 Biome (1.9.4)

[error] 98-98: Alternative text title element cannot be empty

For accessibility purposes, SVGs should have an alternative text, provided via title element. If the svg element has role="img", you should add the aria-label or aria-labelledby attribute.

(lint/a11y/noSvgWithoutTitle)


107-107: 🧹 Nitpick (assertive)

Use self-closing tag for <TextBlock> without children.

When a JSX element has no children, it should be self-closed for cleaner syntax.

Apply this diff:

-      <TextBlock body={`${t("ATTENDANCE_PROJECT_NAME")} *`}></TextBlock>
+      <TextBlock body={`${t("ATTENDANCE_PROJECT_NAME")} *"} />
🧰 Tools
🪛 Biome (1.9.4)

[error] 107-107: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead

(lint/style/useSelfClosingElements)


121-121: 🧹 Nitpick (assertive)

Use self-closing tag for <Divider> component.

The <Divider> component has no children and should be self-closed.

Apply this diff:

-      <Divider></Divider>
+      <Divider />
🧰 Tools
🪛 Biome (1.9.4)

[error] 121-121: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead

(lint/style/useSelfClosingElements)


137-151: 🧹 Nitpick (assertive)

Convert BoundaryComponent to a self-closing tag.

Since BoundaryComponent does not have children, it should be self-closed.

Apply this diff:

                 <BoundaryComponent
                   reset={reset}
                   makeReset={() => {
                     setReset(false);
                   }}
                   isRequired={isRequired}
                   initialValue={Digit.SessionStorage.get("selectedValues")}
                   updateSeeeionStorage={(newSelectedValues) => {
                     Digit.SessionStorage.set("selectedValues", JSON.stringify(newSelectedValues));
                   }}
                   onChange={onChangeId}
                   selectedProject={projectSelected}
                   lowestLevel={Digit.SessionStorage.get("paymentConfig")?.lowestLevelBoundary || lowerBoundaryDefaultSet}
-                ></BoundaryComponent>
+                />
🧰 Tools
🪛 Biome (1.9.4)

[error] 137-150: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead

(lint/style/useSelfClosingElements)


123-134: 🧹 Nitpick (assertive)

Remove commented-out code to keep the codebase clean.

The section from lines 123 to 134 is commented out. If it's no longer needed, consider removing it.

Apply this diff:

-            {/*project && <div style={{ maxWidth: "100%", width: "100%", marginBottom: "24px" }}>
-              <TextBlock body={`${t("ATTENDANCE_PROJECT_NAME")} *`}></TextBlock>
-              <Dropdown
-                t={t}
-                option={project}
-                name={"code"}
-                optionKey={"name"}
-                select={(value) => {
-                  handleProjectChange(value);
-                }}
-              />
-            </div>*/}

8-8: 🧹 Nitpick (assertive)

Remove unused prop projectData.

The projectData prop is declared but never used within CustomFilter. Removing it will clean up the component's interface.

Apply this diff:

-const CustomFilter = ({ resetTable, isRequired, onProjectSelect, onFilterChange, projectData }) => {
+const CustomFilter = ({ resetTable, isRequired, onProjectSelect, onFilterChange }) => {
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/custom_inbox_composer.js (10)

1-1: ⚠️ Potential issue

Remove the unused named import use from React.

The use hook is not a valid named export from React and will cause an error.

Apply this diff:

-import React, { useEffect, useReducer, useState, useMemo, use } from "react";
+import React, { useEffect, useReducer, useState, useMemo } from "react";

13-40: 🧹 Nitpick (assertive)

Consolidate and avoid duplication in JSDoc comments.

The business flow description is duplicated in multiple comment blocks. Consider consolidating them into one block to reduce redundancy.


44-56: 🧹 Nitpick (assertive)

Consider consolidating related state variables into a single state object.

Combining related state variables (filterCriteria, selectedProject, currentPage, etc.) into a single state object can simplify state management.


68-68: 🧹 Nitpick (assertive)

Simplify boolean expression in setCard.

The ternary operator returning true or false is unnecessary. You can directly assign the condition's result.

Apply this diff:

-      setCard(data?.totalCount > 0 ? true : false);
+      setCard(data?.totalCount > 0);

237-237: 🧹 Nitpick (assertive)

Use self-closing tag for <Card> component without children.

The <Card> component on line 237 has no children and should be self-closed.

Apply this diff:

                    <Card style={{ maxWidth: "100%", overflow: "auto", margin: "0px", padding: "0px" }}></Card>
+                   <Card style={{ maxWidth: "100%", overflow: "auto", margin: "0px", padding: "0px" }} />
🧰 Tools
🪛 Biome (1.9.4)

[error] 237-237: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead

(lint/style/useSelfClosingElements)


239-248: 🧹 Nitpick (assertive)

Convert <CustomInboxTable> to a self-closing tag.

Since <CustomInboxTable> has no children, it can be self-closed for cleaner syntax.

Apply this diff:

                    <CustomInboxTable
                      statusCount={childrenData?.statusCount}
                      handleTabChange={callServiceOnTap}
                      rowsPerPage={rowsPerPage}
                      customHandleRowsPerPageChange={handleRowsPerPageChange}
                      customHandlePaginationChange={handlePaginationChange}
                      isLoading={childrenDataLoading}
                      tableData={childrenData?.data}
                      totalCount={childrenData?.totalCount}
-                    ></CustomInboxTable>
+                    />
🧰 Tools
🪛 Biome (1.9.4)

[error] 239-248: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead

(lint/style/useSelfClosingElements)


224-230: 🧹 Nitpick (assertive)

Convert <CustomFilter> to a self-closing tag.

The <CustomFilter> component does not have children and can be self-closed.

Apply this diff:

                  <CustomFilter
                    resetTable={resetTable}
                    isRequired={ScreenTypeEnum.REGISTER}
                    onProjectSelect={handleProjectChange}
                    projectData={selectedProject}
                    onFilterChange={handleFilterUpdate}
-                  ></CustomFilter>
+                  />
🧰 Tools
🪛 Biome (1.9.4)

[error] 224-230: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead

(lint/style/useSelfClosingElements)


209-209: 🧹 Nitpick (assertive)

Use self-closing tag for <CustomInboxSearchLinks> component.

The <CustomInboxSearchLinks> component has no children and should be self-closed.

Apply this diff:

                <CustomInboxSearchLinks headerText={"ATTENDANCE_INBOX_CARD"}></CustomInboxSearchLinks>
+               <CustomInboxSearchLinks headerText={"ATTENDANCE_INBOX_CARD"} />
🧰 Tools
🪛 Biome (1.9.4)

[error] 209-209: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead

(lint/style/useSelfClosingElements)


113-113: 🧹 Nitpick (assertive)

Remove or clarify the commented-out error handling.

The comment /// will show estimate data only is ambiguous. Clarify its purpose or remove it if it's obsolete.


170-194: 🧹 Nitpick (assertive)

Optimize event handlers and remove commented code.

Consider debouncing the triggerMusterRollApprove calls to prevent excessive API calls. Also, remove any commented-out code if it's no longer needed.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 12b115b and a619132.

📒 Files selected for processing (5)
  • health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/PaymentsCard.js (1 hunks)
  • health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/bill_inbox/bill_boundary_filter.js (1 hunks)
  • health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/custom_comp/filter_section.js (1 hunks)
  • health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/custom_inbox_composer.js (1 hunks)
  • health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/sample.js (1 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/PaymentsCard.js (1)

Pattern **/*.js: check

health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/custom_inbox_composer.js (1)

Pattern **/*.js: check

health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/bill_inbox/bill_boundary_filter.js (1)

Pattern **/*.js: check

health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/custom_comp/filter_section.js (1)

Pattern **/*.js: check

health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/sample.js (1)

Pattern **/*.js: check

🪛 Biome (1.9.4)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/PaymentsCard.js

[error] 24-24: Avoid unnecessary callback in flatMap call.

You can just use flat to flatten the array.
Safe fix: Replace unnecessary flatMap call to flat instead.

(lint/correctness/noFlatMapIdentity)

health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/custom_inbox_composer.js

[error] 209-209: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead

(lint/style/useSelfClosingElements)


[error] 224-230: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead

(lint/style/useSelfClosingElements)


[error] 237-237: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead

(lint/style/useSelfClosingElements)


[error] 239-248: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead

(lint/style/useSelfClosingElements)

health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/bill_inbox/bill_boundary_filter.js

[error] 71-81: Enforce to have the onClick mouse event with the onKeyUp, the onKeyDown, or the onKeyPress keyboard event.

Actions triggered using mouse events should have corresponding keyboard events to account for keyboard-only navigation.

(lint/a11y/useKeyWithClickEvents)


[error] 86-86: Enforce to have the onClick mouse event with the onKeyUp, the onKeyDown, or the onKeyPress keyboard event.

Actions triggered using mouse events should have corresponding keyboard events to account for keyboard-only navigation.

(lint/a11y/useKeyWithClickEvents)


[error] 87-87: Alternative text title element cannot be empty

For accessibility purposes, SVGs should have an alternative text, provided via title element. If the svg element has role="img", you should add the aria-label or aria-labelledby attribute.

(lint/a11y/noSvgWithoutTitle)

health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/custom_comp/filter_section.js

[error] 92-97: Enforce to have the onClick mouse event with the onKeyUp, the onKeyDown, or the onKeyPress keyboard event.

Actions triggered using mouse events should have corresponding keyboard events to account for keyboard-only navigation.

(lint/a11y/useKeyWithClickEvents)


[error] 98-98: Alternative text title element cannot be empty

For accessibility purposes, SVGs should have an alternative text, provided via title element. If the svg element has role="img", you should add the aria-label or aria-labelledby attribute.

(lint/a11y/noSvgWithoutTitle)


[error] 107-107: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead

(lint/style/useSelfClosingElements)


[error] 121-121: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead

(lint/style/useSelfClosingElements)


[error] 137-150: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead

(lint/style/useSelfClosingElements)


[error] 41-41: This let declares a variable that is only assigned once.

'datak' is never reassigned.

Safe fix: Use const instead.

(lint/style/useConst)

health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/sample.js

[error] 216-216: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)

🔇 Additional comments (12)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/PaymentsCard.js (5)

11-12: Document the session storage cleanup rationale

The addition of session storage cleanup could affect state persistence. Please add comments explaining why these items need to be cleared on component mount.

Could you verify if this cleanup:

  1. Is intentional and necessary
  2. Won't cause issues if the component remounts while the user is actively using it
  3. Won't affect other components that might depend on this data

29-31: LGTM! Well-structured link generation with role-based access

The link generation is well-organized with appropriate role-based access control for each functionality.


34-36: LGTM! Clear and concise role validation

The role checking logic is well-implemented with proper null checks and role validation.


44-44: Verify styling class name convention

Please confirm that "microplan-employee-module-card" follows the project's naming conventions for CSS classes.

Run this script to check for consistent class naming patterns:

#!/bin/bash
# Search for similar class naming patterns in the codebase
rg -i 'className.*employee.*module.*card' health/micro-ui/web/micro-ui-internals/

23-23: 🧹 Nitpick (assertive)

Optimize array flattening operation

The flatMap usage can be simplified.

Apply this diff to optimize the array flattening:

-if (!Digit.Utils.didEmployeeHasAtleastOneRole(Object.values(ROLES).flatMap((e) => e))) {
+if (!Digit.Utils.didEmployeeHasAtleastOneRole(Object.values(ROLES).flat())) {

Likely invalid or redundant comment.

health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/bill_inbox/bill_boundary_filter.js (6)

116-116: 🛠️ Refactor suggestion

Fix typo in prop name

The prop name updateSeeeionStorage contains a typo.

-   updateSeeeionStorage={(newSelectedValues) => {
+   updateSessionStorage={(newSelectedValues) => {

Likely invalid or redundant comment.


3-3: 🛠️ Refactor suggestion

Remove unused import CheckBox

The CheckBox component is imported but never used in this file.

- import { CheckBox, SubmitBar } from "@egovernments/digit-ui-components";
+ import { SubmitBar } from "@egovernments/digit-ui-components";

Likely invalid or redundant comment.


51-55: 🛠️ Refactor suggestion

Use consistent state reset values

The boundary state is reset using an empty string in handleClearFilter but null elsewhere in the code. This inconsistency could lead to bugs.

    const handleClearFilter = () => {
        setResetFilters(true);
-       setBoundary(""); // Clear the boundary value
+       setBoundary(null); // Clear the boundary value
        setBoundaryKey((prevKey) => prevKey + 1);
    };

Likely invalid or redundant comment.


36-44: ⚠️ Potential issue

Add missing dependency to useEffect

The updateBoundaryFilters value is used inside the effect but not included in the dependency array. This could lead to stale closures.

    }, [levelSelected])
+   }, [levelSelected, updateBoundaryFilters])

Likely invalid or redundant comment.


71-81: ⚠️ Potential issue

Add keyboard event handlers for accessibility

The div with onClick handler should support keyboard navigation.

    <div 
        onClick={handleClearFilter}
+       onKeyPress={(e) => { if (e.key === 'Enter') handleClearFilter(); }}
+       role="button"
+       tabIndex={0}
        style={{

Likely invalid or redundant comment.

🧰 Tools
🪛 Biome (1.9.4)

[error] 71-81: Enforce to have the onClick mouse event with the onKeyUp, the onKeyDown, or the onKeyPress keyboard event.

Actions triggered using mouse events should have corresponding keyboard events to account for keyboard-only navigation.

(lint/a11y/useKeyWithClickEvents)


87-92: ⚠️ Potential issue

Add accessibility attributes to SVG

SVG elements should have proper accessibility attributes for screen readers.

    <svg 
+       role="img"
+       aria-label={t("HCM_AM_REFRESH")}
        width="17" 
        height="17" 
        viewBox="0 0 16 22"
    >

Likely invalid or redundant comment.

🧰 Tools
🪛 Biome (1.9.4)

[error] 87-87: Alternative text title element cannot be empty

For accessibility purposes, SVGs should have an alternative text, provided via title element. If the svg element has role="img", you should add the aria-label or aria-labelledby attribute.

(lint/a11y/noSvgWithoutTitle)

health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/custom_comp/filter_section.js (1)

92-97: ⚠️ Potential issue

Add keyboard event handling for accessibility.

The <span> element with an onClick handler should also handle keyboard events to be accessible for users who navigate via keyboard.

Apply this diff:

               onClick={() => {
                 setReset(true);
               }}
+              onKeyPress={(e) => {
+                if (e.key === "Enter") {
+                  setReset(true);
+                }
+              }}
               style={{ border: "1px solid #e0e0e0", padding: "6px", marginBottom: "10px", cursor: "pointer" }}
               tabIndex="0"
               role="button"

This ensures that the element is accessible via keyboard navigation.

Likely invalid or redundant comment.

🧰 Tools
🪛 Biome (1.9.4)

[error] 92-97: Enforce to have the onClick mouse event with the onKeyUp, the onKeyDown, or the onKeyPress keyboard event.

Actions triggered using mouse events should have corresponding keyboard events to account for keyboard-only navigation.

(lint/a11y/useKeyWithClickEvents)

import { CheckBox, SubmitBar } from "@egovernments/digit-ui-components";
import BoundaryComponent from "../sample";
import { Card, SVG, Button, ButtonGroup, TextBlock, Dropdown, Toast } from "@egovernments/digit-ui-components";
const BillBoundaryFilter = ({ isRequired, selectedProject, selectedLevel, onFilterChange, updateBoundaryFilters }) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Add PropTypes or TypeScript definitions

Add prop type definitions to improve code maintainability and catch potential type-related issues early.

Example with PropTypes:

import PropTypes from 'prop-types';

BillBoundaryFilter.propTypes = {
  isRequired: PropTypes.bool,
  selectedProject: PropTypes.object,
  selectedLevel: PropTypes.object,
  onFilterChange: PropTypes.func.isRequired,
  updateBoundaryFilters: PropTypes.bool
};

Comment on lines +95 to +106
{/*project && <div style={{ maxWidth: "100%", width: "100%", marginBottom: "24px" }}>
<TextBlock body={`${t("ATTENDANCE_PROJECT_NAME")} *`}></TextBlock>
<Dropdown
t={t}
option={project}
name={"code"}
optionKey={"name"}
select={(value) => {
handleProjectChange(value);
}}
/>
</div>*/}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Remove commented code

Remove the commented-out code block. If this code might be needed later, track it in version control instead.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

♻️ Duplicate comments (1)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/my_bills.js (1)

79-84: ⚠️ Potential issue

Security: Remove hardcoded report IDs.

The presence of hardcoded UUIDs could pose a security risk if these are actual production IDs.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a619132 and a4b50c7.

📒 Files selected for processing (7)
  • health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/PaymentsCard.js (1 hunks)
  • health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/bill_inbox/BillInbox.js (1 hunks)
  • health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/bill_inbox/bill_boundary_filter.js (1 hunks)
  • health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/custom_inbox_composer.js (1 hunks)
  • health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/sample.js (1 hunks)
  • health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/index.js (1 hunks)
  • health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/my_bills.js (1 hunks)
🧰 Additional context used
📓 Path-based instructions (7)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/PaymentsCard.js (1)

Pattern **/*.js: check

health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/custom_inbox_composer.js (1)

Pattern **/*.js: check

health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/my_bills.js (1)

Pattern **/*.js: check

health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/bill_inbox/BillInbox.js (1)

Pattern **/*.js: check

health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/sample.js (1)

Pattern **/*.js: check

health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/bill_inbox/bill_boundary_filter.js (1)

Pattern **/*.js: check

health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/index.js (1)

Pattern **/*.js: check

🪛 Biome (1.9.4)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/PaymentsCard.js

[error] 29-29: Avoid unnecessary callback in flatMap call.

You can just use flat to flatten the array.
Safe fix: Replace unnecessary flatMap call to flat instead.

(lint/correctness/noFlatMapIdentity)

health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/custom_inbox_composer.js

[error] 210-210: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead

(lint/style/useSelfClosingElements)


[error] 225-231: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead

(lint/style/useSelfClosingElements)


[error] 238-238: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead

(lint/style/useSelfClosingElements)


[error] 240-249: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead

(lint/style/useSelfClosingElements)

health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/my_bills.js

[error] 36-36: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)

health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/bill_inbox/BillInbox.js

[error] 48-48: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


[error] 51-51: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


[error] 68-68: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


[error] 193-201: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead

(lint/style/useSelfClosingElements)


[error] 204-205: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead

(lint/style/useSelfClosingElements)


[error] 218-225: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead

(lint/style/useSelfClosingElements)


[error] 262-271: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead

(lint/style/useSelfClosingElements)


[error] 281-293: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)


[error] 304-320: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)

health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/sample.js

[error] 216-216: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)

health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/bill_inbox/bill_boundary_filter.js

[error] 75-85: Enforce to have the onClick mouse event with the onKeyUp, the onKeyDown, or the onKeyPress keyboard event.

Actions triggered using mouse events should have corresponding keyboard events to account for keyboard-only navigation.

(lint/a11y/useKeyWithClickEvents)


[error] 90-90: Enforce to have the onClick mouse event with the onKeyUp, the onKeyDown, or the onKeyPress keyboard event.

Actions triggered using mouse events should have corresponding keyboard events to account for keyboard-only navigation.

(lint/a11y/useKeyWithClickEvents)


[error] 91-91: Alternative text title element cannot be empty

For accessibility purposes, SVGs should have an alternative text, provided via title element. If the svg element has role="img", you should add the aria-label or aria-labelledby attribute.

(lint/a11y/noSvgWithoutTitle)

🔇 Additional comments (40)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/my_bills.js (5)

1-8: Optimize imports for better maintainability.

  1. Consolidate imports from similar packages (@egovernments/digit-ui-react-components and @egovernments/digit-ui-components)
  2. Remove unused imports: useMemo, InboxSearchComposer

16-20: Initialize date state with null values for consistency.


22-22: Add null check for SessionStorage access.


43-50: Fix effect dependencies and consolidate storage cleanup.


112-127: Improve loading states and accessibility.

health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/bill_inbox/bill_boundary_filter.js (7)

3-3: Remove unused import CheckBox

The CheckBox component imported from @egovernments/digit-ui-components is not used in this file. Removing it will clean up the code.


45-45: Add updateBoundaryFilters to the dependency array in useEffect

The useEffect hook uses updateBoundaryFilters but does not include it in the dependency array. This could lead to unexpected behavior if updateBoundaryFilters changes without triggering the effect.


54-54: Ensure consistent reset of boundary state

In handleClearFilter, you reset boundary using setBoundary(""), whereas in other parts of the code, setBoundary(null) is used. For consistency and to prevent potential issues, consider using null throughout to represent an unset boundary.


75-85: Enhance accessibility by adding keyboard event handlers

The <div> element with an onClick handler should support keyboard interactions for accessibility. Add onKeyPress and tabIndex={0} to enable keyboard navigation for users who rely on keyboards.

🧰 Tools
🪛 Biome (1.9.4)

[error] 75-85: Enforce to have the onClick mouse event with the onKeyUp, the onKeyDown, or the onKeyPress keyboard event.

Actions triggered using mouse events should have corresponding keyboard events to account for keyboard-only navigation.

(lint/a11y/useKeyWithClickEvents)


90-90: Improve accessibility of the clickable <span> element

The <span> element with an onClick handler should support keyboard interactions and have appropriate accessibility attributes. Consider changing it to a <button> or adding tabIndex and onKeyPress to enhance accessibility.

🧰 Tools
🪛 Biome (1.9.4)

[error] 90-90: Enforce to have the onClick mouse event with the onKeyUp, the onKeyDown, or the onKeyPress keyboard event.

Actions triggered using mouse events should have corresponding keyboard events to account for keyboard-only navigation.

(lint/a11y/useKeyWithClickEvents)


91-91: Provide alternative text for SVG elements

The <svg> element should include accessibility attributes such as role="img" and aria-label or a <title> element to describe the image for assistive technologies.

🧰 Tools
🪛 Biome (1.9.4)

[error] 91-91: Alternative text title element cannot be empty

For accessibility purposes, SVGs should have an alternative text, provided via title element. If the svg element has role="img", you should add the aria-label or aria-labelledby attribute.

(lint/a11y/noSvgWithoutTitle)


120-120: Fix the spelling of updateSeeeionStorage

The prop updateSeeeionStorage appears to be misspelled. Correcting it to updateSessionStorage will improve code readability and avoid confusion.

health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/sample.js (5)

6-6: Fix the spelling of updateSeeeionStorage

The prop updateSeeeionStorage in BoundaryComponent is misspelled. Correcting it to updateSessionStorage will improve readability and prevent potential confusion.


7-7: Add null check before accessing boundaryHierarchyOrder

Ensure that Digit.SessionStorage.get("boundaryHierarchyOrder") returns a valid array before calling .map on it to avoid potential runtime errors if the session storage item is null or undefined.


32-33: Clarify the usage of lowest versus lowestLevel

Variables lowest and lowestLevel seem to represent similar concepts. Consider consolidating them or renaming one to enhance code clarity and reduce confusion.


216-216: Simplify the boolean expression for isRequired

The conditional assignment to isRequired can be simplified for better readability. Instead of using a ternary operator, you can use logical expressions.

🧰 Tools
🪛 Biome (1.9.4)

[error] 216-216: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


248-248: Simplify the boolean check for isRequired in TextBlock

You can simplify the expression isRequired == true to just isRequired for cleaner and more concise code.

health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/bill_inbox/BillInbox.js (12)

1-1: Remove unused and invalid imports

The imports useReducer, useMemo, and use are not used in this file. Additionally, use is not a valid React hook and may have been included by mistake. Please remove these to clean up the code.

Apply this diff:

- import React, { useEffect, useReducer, useState, useMemo, use } from "react";
+ import React, { useEffect, useState } from "react";

5-5: Define location or use useLocation hook

The variable location is used but not defined in this scope. If you intend to access the browser's location or the route's state, consider importing useLocation from react-router-dom and using it to retrieve the location object.

Apply this diff to import useLocation and update the code:

+ import { useLocation } from "react-router-dom";

...

- const { fromViewScreen } = location.state || false;
+ const location = useLocation();
+ const { fromViewScreen } = location.state || {};

23-23: Remove commented-out code

The commented-out line is unnecessary and can be removed to keep the code clean.

Apply this diff:

- // const [selectedBoundaryCode, setSelectedBoundaryCode] = useState(null);

44-44: Use triple equals and optional chaining for session storage

Using triple equals avoids subtle type-coercion pitfalls. Also, consider optional chaining on Digit.SessionStorage.get("paymentInbox") to prevent potential runtime errors if the stored object is missing.

Apply this diff:

- referenceId: selectedProject == undefined ? Digit.SessionStorage.get("paymentInbox").selectedProject?.id : selectedProject?.id,
+ referenceId: selectedProject === undefined
+   ? Digit.SessionStorage.get("paymentInbox")?.selectedProject?.id
+   : selectedProject?.id,

48-48: Simplify the boolean expression

Instead of using a ternary operator returning true/false from a logical expression, you can directly assign the expression's result.

Apply this diff:

- isChildrenRequired: selectedLevel != null && selectedLevel?.code === "DISTRICT" ? true : false,
+ isChildrenRequired: !!(selectedLevel != null && selectedLevel?.code === "DISTRICT"),
🧰 Tools
🪛 Biome (1.9.4)

[error] 48-48: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


51-51: Simplify the boolean expression

Instead of using a ternary operator returning true/false from a logical expression, you can directly assign the expression's result.

Apply this diff:

- enabled: selectedBoundaryCode && selectedProject ? true : false,
+ enabled: !!(selectedBoundaryCode && selectedProject),
🧰 Tools
🪛 Biome (1.9.4)

[error] 51-51: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


193-201: Use a self-closing tag for <CustomInboxSearchLinks>

When a JSX element has no child content, prefer using a self-closing tag.

Apply this diff:

- <CustomInboxSearchLinks
-     headerText={"HCM_AM_BILL_INBOX"}
-     links={[
-         {
-             url: "/employee/payments/my-bills",
-             text: "HCM_AM_MY_BILLS",
-         },
-     ]}
- ></CustomInboxSearchLinks>
+ <CustomInboxSearchLinks
+     headerText={"HCM_AM_BILL_INBOX"}
+     links={[
+         {
+             url: "/employee/payments/my-bills",
+             text: "HCM_AM_MY_BILLS",
+         },
+     ]}
+ />
🧰 Tools
🪛 Biome (1.9.4)

[error] 193-201: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead

(lint/style/useSelfClosingElements)


204-205: Use a self-closing tag for <BillSearchBox>

JSX elements without child content should be self-closing.

Apply this diff:

- <BillSearchBox onLevelSelect={handleSearchChange} initialProject={selectedProject}
-     initialAggregationLevel={selectedLevel}></BillSearchBox>
+ <BillSearchBox onLevelSelect={handleSearchChange} initialProject={selectedProject}
+     initialAggregationLevel={selectedLevel} />
🧰 Tools
🪛 Biome (1.9.4)

[error] 204-205: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead

(lint/style/useSelfClosingElements)


281-293: Add a key property when returning elements in an array

When returning an array of elements in JSX, each element should have a unique key prop to help React identify which items have changed.

Apply this diff:

 actionFields={[
-    <Button
+    <Button
+        key="generate-bill-btn"
         icon="CheckCircle"
         label={t(`HCM_AM_GENERATE_BILL_LABEL`)}
         onClick={() => {
             triggerGenerateBill();
         }}
         style={{
             minWidth: "14rem",
         }}
         type="button"
         variation="primary"
         isDisabled={generateBillMutation.isLoading}
     />,
 ]}
🧰 Tools
🪛 Biome (1.9.4)

[error] 281-293: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)


304-320: Add a key property when returning elements in an array

When returning an array of elements in JSX, each element should have a unique key prop to help React identify which items have changed.

Apply this diff:

 actionFields={[
-    <Button
+    <Button
+        key="generate-bill-btn"
         icon="CheckCircle"
         label={t(`HCM_AM_GENERATE_BILL_LABEL`)}
         onClick={() => {
             !showGenerateBillAction || BillData?.bills?.length >= 0
                 ? setShowToast({ key: "info", label: t("HCM_AM_GENERATE_BILLS_CANNOT_BE_CALLED_INFO_MESSAGE"), transitionTime: 5000 })
                 : triggerGenerateBill();
         }}
         style={{
             minWidth: "14rem",
             cursor: !showGenerateBillAction || BillData?.bills?.length >= 0 ? "not-allowed" : "pointer",
             opacity: !showGenerateBillAction || BillData?.bills?.length >= 0 ? 0.5 : 1,
         }}
         type="button"
         variation="primary"
         isDisabled={generateBillMutation.isLoading}
     />,
 ]}
🧰 Tools
🪛 Biome (1.9.4)

[error] 304-320: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)


308-310: Logical error in the onClick handler condition

The condition in the onClick handler may contain a logical error. The expression BillData?.bills?.length >= 0 will always be true when length is 0 or more, meaning it will always evaluate to true, and triggerGenerateBill() will not be called.

Consider revising the condition to correctly reflect the intended logic. If you intend to check if there are no bills, you might use:

- !showGenerateBillAction || BillData?.bills?.length >= 0
+ !showGenerateBillAction || BillData?.bills?.length > 0

Alternatively, adjust the condition to match your intended logic.


68-68: 🧹 Nitpick (assertive)

Simplify the boolean expression

Instead of using a ternary operator returning true/false from a logical expression, you can directly assign the expression's result.

Apply this diff:

- enabled: selectedBoundaryCode ? true : false,
+ enabled: !!selectedBoundaryCode,

Likely invalid or redundant comment.

🧰 Tools
🪛 Biome (1.9.4)

[error] 68-68: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)

health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/index.js (3)

18-18: Handle potential undefined state in useLocation

Destructuring from local?.state || false may cause an error if local.state is undefined because destructuring properties from false is invalid. Consider defaulting to an empty object {} instead to ensure safe destructuring.

Apply this diff to fix the issue:

- const { fromCampaignSupervisor } = local?.state || false;
+ const { fromCampaignSupervisor } = local?.state || {};

46-46: Use optional chaining with window.contextPath to prevent runtime errors

Accessing window.contextPath without optional chaining may cause a runtime error if contextPath is undefined. Consider using window?.contextPath.

Apply this diff to fix the issue:

- if (window.location.pathname !== `/${window.contextPath}/employee/`) {
+ if (window.location.pathname !== `/${window?.contextPath}/employee/`) {

61-67: Avoid inline function components in routes for performance

Using inline arrow functions in component={() => <Component />} can lead to unnecessary re-renders. Instead, pass the component reference directly or use children to enhance performance.

Apply this diff to refactor:

- <PrivateRoute path={`${path}/view-attendance`} component={() => <ViewAttendance />} />
- <PrivateRoute path={`${path}/edit-attendance`} component={() => <ViewAttendance editAttendance={true} />} />
- <PrivateRoute path={`${path}/attendance-approve-success`} component={() => <Response />} />
- <PrivateRoute path={`${path}/attendance-approve-failed`} component={() => <Response />} />
- <PrivateRoute path={`${path}/registers-inbox`} component={() => <AttendanceInbox />} />
- <PrivateRoute path={`${path}/generate-bill`} component={() => <BillInbox />} />
- <PrivateRoute path={`${path}/my-bills`} component={() => <MyBills />} />
+ <PrivateRoute path={`${path}/view-attendance`} component={ViewAttendance} />
+ <PrivateRoute path={`${path}/edit-attendance`}>
+   <ViewAttendance editAttendance={true} />
+ </PrivateRoute>
+ <PrivateRoute path={`${path}/attendance-approve-success`} component={Response} />
+ <PrivateRoute path={`${path}/attendance-approve-failed`} component={Response} />
+ <PrivateRoute path={`${path}/registers-inbox`} component={AttendanceInbox} />
+ <PrivateRoute path={`${path}/generate-bill`} component={BillInbox} />
+ <PrivateRoute path={`${path}/my-bills`} component={MyBills} />
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/custom_inbox_composer.js (6)

1-1: Remove the unused named import use from React

There is no use named export from react, and attempting to import it will cause an error. Please remove it to prevent compilation issues.

Apply this diff to fix the issue:

- import React, { useEffect, useReducer, useState, useMemo, use } from "react";
+ import React, { useEffect, useReducer, useState, useMemo } from "react";

13-40: Enhance JSDoc documentation with parameter and return type information

While the business flow documentation is comprehensive, consider adding @param tags for component props and an @returns tag describing the rendered output for better clarity.


210-210: Use self-closing tag for JSX elements without children

The CustomInboxSearchLinks component has no children and can be self-closed to improve readability.

Apply this diff:

- <CustomInboxSearchLinks headerText={"ATTENDANCE_INBOX_CARD"}></CustomInboxSearchLinks>
+ <CustomInboxSearchLinks headerText={"ATTENDANCE_INBOX_CARD"} />
🧰 Tools
🪛 Biome (1.9.4)

[error] 210-210: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead

(lint/style/useSelfClosingElements)


238-238: Use self-closing tag for <Card> component without children

The <Card> component has no children and can be self-closed to improve readability.

Apply this diff:

- <Card style={{ maxWidth: "100%", overflow: "auto", margin: "0px", padding: "0px" }}></Card>
+ <Card style={{ maxWidth: "100%", overflow: "auto", margin: "0px", padding: "0px" }} />
🧰 Tools
🪛 Biome (1.9.4)

[error] 238-238: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead

(lint/style/useSelfClosingElements)


225-231: 🧹 Nitpick (assertive)

Use self-closing tag for <CustomFilter> component

Since <CustomFilter> does not contain children, it can be self-closed to enhance code clarity.

Apply this diff:

- <CustomFilter
    resetTable={resetTable}
    isRequired={ScreenTypeEnum.REGISTER}
    onProjectSelect={handleProjectChange}
    projectData={selectedProject}
    onFilterChange={handleFilterUpdate}
  ></CustomFilter>
+ <CustomFilter
    resetTable={resetTable}
    isRequired={ScreenTypeEnum.REGISTER}
    onProjectSelect={handleProjectChange}
    projectData={selectedProject}
    onFilterChange={handleFilterUpdate}
  />

Likely invalid or redundant comment.

🧰 Tools
🪛 Biome (1.9.4)

[error] 225-231: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead

(lint/style/useSelfClosingElements)


240-249: 🧹 Nitpick (assertive)

Use self-closing tag for <CustomInboxTable> component

Since <CustomInboxTable> does not contain children, it can be self-closed to enhance code clarity.

Apply this diff:

- <CustomInboxTable
    statusCount={childrenData?.statusCount}
    handleTabChange={callServiceOnTap}
    rowsPerPage={rowsPerPage}
    customHandleRowsPerPageChange={handleRowsPerPageChange}
    customHandlePaginationChange={handlePaginationChange}
    isLoading={childrenDataLoading}
    tableData={childrenData?.data}
    totalCount={childrenData?.totalCount}
  ></CustomInboxTable>
+ <CustomInboxTable
    statusCount={childrenData?.statusCount}
    handleTabChange={callServiceOnTap}
    rowsPerPage={rowsPerPage}
    customHandleRowsPerPageChange={handleRowsPerPageChange}
    customHandlePaginationChange={handlePaginationChange}
    isLoading={childrenDataLoading}
    tableData={childrenData?.data}
    totalCount={childrenData?.totalCount}
  />

Likely invalid or redundant comment.

🧰 Tools
🪛 Biome (1.9.4)

[error] 240-249: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead

(lint/style/useSelfClosingElements)

health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/PaymentsCard.js (2)

11-17: Ensure consistent session storage management

The addition of multiple Digit.SessionStorage.del calls enhances session management by clearing specific data upon component mount. Ensure that this aligns with the application's overall session handling strategy.


29-29: Simplify flatMap usage to flat

The callback in Object.values(ROLES).flatMap((e) => e) is unnecessary as it returns the elements directly. Simplify by using flat() instead.

Apply this diff:

- if (!Digit.Utils.didEmployeeHasAtleastOneRole(Object.values(ROLES).flatMap((e) => e))) {
+ if (!Digit.Utils.didEmployeeHasAtleastOneRole(Object.values(ROLES).flat())) {
🧰 Tools
🪛 Biome (1.9.4)

[error] 29-29: Avoid unnecessary callback in flatMap call.

You can just use flat to flatten the array.
Safe fix: Replace unnecessary flatMap call to flat instead.

(lint/correctness/noFlatMapIdentity)

Comment on lines 24 to 41
const BillSearchCri = {
url: `/health-expense/bill/v1/_search`,
body: {
billCriteria: {
tenantId: tenantId,
// ...(project?.[0]?.address?.boundaryType !== "COUNTRY" ? { localityCode: project?.[0]?.address?.boundary } : {}),
referenceIds: [project?.[0]?.id],
...(billID ? { billNumbers: [billID] } : {}),
...(dateRange.startDate && dateRange.endDate ? { fromDate: new Date(dateRange.startDate).getTime(), toDate: new Date(dateRange.endDate).getTime() } : {})
}
},
config: {
enabled: project ? true : false,
select: (data) => {
return data;
},
},
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add error handling for API failures.

The API configuration lacks proper error handling which could lead to silent failures. Consider adding error boundaries or error states to handle API failures gracefully.

 const BillSearchCri = {
     config: {
         enabled: Boolean(project),
         select: (data) => {
+            if (!data?.bills) {
+                throw new Error('Invalid response format');
+            }
             return data;
         },
+        onError: (error) => {
+            console.error('Bill search failed:', error);
+            Digit.NotificationService.error(
+                t('HCM_AM_BILL_FETCH_ERROR'),
+                error.message
+            );
+        }
     },
 };

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 Biome (1.9.4)

[error] 36-36: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)

Comment on lines +218 to +225
<BillBoundaryFilter
isRequired={ScreenTypeEnum.BILL}
selectedProject={selectedProject}
selectedLevel={selectedLevel}
onFilterChange={handleFilterUpdate}
updateBoundaryFilters={updateFilters}
resetBoundaryFilter={resetBoundaryFilter}
></BillBoundaryFilter>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Use a self-closing tag for <BillBoundaryFilter>

JSX elements without child content should be self-closing.

Apply this diff:

- <BillBoundaryFilter
-     isRequired={ScreenTypeEnum.BILL}
-     selectedProject={selectedProject}
-     selectedLevel={selectedLevel}
-     onFilterChange={handleFilterUpdate}
-     updateBoundaryFilters={updateFilters}
-     resetBoundaryFilter={resetBoundaryFilter}
- ></BillBoundaryFilter>
+ <BillBoundaryFilter
+     isRequired={ScreenTypeEnum.BILL}
+     selectedProject={selectedProject}
+     selectedLevel={selectedLevel}
+     onFilterChange={handleFilterUpdate}
+     updateBoundaryFilters={updateFilters}
+     resetBoundaryFilter={resetBoundaryFilter}
+ />
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<BillBoundaryFilter
isRequired={ScreenTypeEnum.BILL}
selectedProject={selectedProject}
selectedLevel={selectedLevel}
onFilterChange={handleFilterUpdate}
updateBoundaryFilters={updateFilters}
resetBoundaryFilter={resetBoundaryFilter}
></BillBoundaryFilter>
<BillBoundaryFilter
isRequired={ScreenTypeEnum.BILL}
selectedProject={selectedProject}
selectedLevel={selectedLevel}
onFilterChange={handleFilterUpdate}
updateBoundaryFilters={updateFilters}
resetBoundaryFilter={resetBoundaryFilter}
/>
🧰 Tools
🪛 Biome (1.9.4)

[error] 218-225: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead

(lint/style/useSelfClosingElements)

Comment on lines +262 to +271
<BillInboxTable
isFetching={isFetching}
tableData={tableData}
currentPage={currentPage}
rowsPerPage={rowsPerPage}
handlePageChange={handlePageChange}
handlePerRowsChange={handlePerRowsChange}
totalCount={totalCount}
status={activeLink.code}
></BillInboxTable>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Use a self-closing tag for <BillInboxTable>

JSX elements without child content should be self-closing.

Apply this diff:

- <BillInboxTable
-     isFetching={isFetching}
-     tableData={tableData}
-     currentPage={currentPage}
-     rowsPerPage={rowsPerPage}
-     handlePageChange={handlePageChange}
-     handlePerRowsChange={handlePerRowsChange}
-     totalCount={totalCount}
-     status={activeLink.code}
- ></BillInboxTable>
+ <BillInboxTable
+     isFetching={isFetching}
+     tableData={tableData}
+     currentPage={currentPage}
+     rowsPerPage={rowsPerPage}
+     handlePageChange={handlePageChange}
+     handlePerRowsChange={handlePerRowsChange}
+     totalCount={totalCount}
+     status={activeLink.code}
+ />
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<BillInboxTable
isFetching={isFetching}
tableData={tableData}
currentPage={currentPage}
rowsPerPage={rowsPerPage}
handlePageChange={handlePageChange}
handlePerRowsChange={handlePerRowsChange}
totalCount={totalCount}
status={activeLink.code}
></BillInboxTable>
<BillInboxTable
isFetching={isFetching}
tableData={tableData}
currentPage={currentPage}
rowsPerPage={rowsPerPage}
handlePageChange={handlePageChange}
handlePerRowsChange={handlePerRowsChange}
totalCount={totalCount}
status={activeLink.code}
/>
🧰 Tools
🪛 Biome (1.9.4)

[error] 262-271: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead

(lint/style/useSelfClosingElements)

Comment on lines +74 to +78
filterData?.code == undefined || filterData?.code == null
? filterCriteria?.code == undefined || filterCriteria?.code == null
? Digit.SessionStorage.get("paymentInbox").code
: filterCriteria?.code
: filterData?.code,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Refactor nested ternary operators for better readability

The nested ternary operators in the localityCode parameter make the code difficult to read and maintain. Consider refactoring to improve clarity.

You can refactor the code as follows:

let localityCode;

if (filterData?.code !== undefined && filterData?.code !== null) {
  localityCode = filterData.code;
} else if (filterCriteria?.code !== undefined && filterCriteria?.code !== null) {
  localityCode = filterCriteria.code;
} else {
  localityCode = Digit.SessionStorage.get("paymentInbox")?.code;
}

// Update the params object
params: {
  // ... other params
  localityCode: localityCode,
  // ... other params
}

return {
label: t(labelKey),
link: `/${window?.contextPath}/employee/payments/${pathSuffix}`,
link: `/payments-ui/employee/payments/${pathSuffix}`,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codebase verification

Use window.contextPath instead of hardcoded /payments-ui prefix

The hardcoded path /payments-ui/employee/payments/${pathSuffix} should be changed to /${window.contextPath}/employee/payments/${pathSuffix} to:

  • Align with the application's routing configuration
  • Maintain consistency with other URLs in the health-payments module
  • Support different environments where CONTEXT_PATH may be configured differently
🔗 Analysis chain

Verify the hardcoded URL path

The link in generateLink uses a hardcoded path /payments-ui/employee/payments/${pathSuffix}. Confirm that this hardcoded path aligns with the application's routing configuration and will work correctly in different environments.

Run the following script to check the usage of window.contextPath in the codebase:

This will help ensure consistent usage and avoid potential routing issues.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Search for usage of window.contextPath in link generation

rg 'window\.contextPath'

Length of output: 34839

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 30ffe96 and b095cba.

📒 Files selected for processing (1)
  • health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/ViewAttendance.js (2 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/ViewAttendance.js (1)

Pattern **/*.js: check

🪛 Biome (1.9.4)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/ViewAttendance.js

[error] 48-48: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


[error] 103-103: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


[error] 280-280: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


[error] 305-307: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


[error] 480-490: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)


[error] 492-504: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)


[error] 506-535: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)

🔇 Additional comments (6)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/ViewAttendance.js (6)

48-48: Simplify boolean expression

The ternary operator is unnecessary here. You can simplify the expression.

🧰 Tools
🪛 Biome (1.9.4)

[error] 48-48: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


103-103: Simplify boolean expression

The ternary operator is unnecessary here. You can simplify the expression.

🧰 Tools
🪛 Biome (1.9.4)

[error] 103-103: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


305-307: Simplify boolean expression

The ternary operator is unnecessary here. You can simplify the expression.

🧰 Tools
🪛 Biome (1.9.4)

[error] 305-307: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


480-490: Add a unique key prop to elements in actionFields

When rendering an array of elements in actionFields, each element should have a unique key prop to help React identify them.

Also applies to: 492-504, 506-535

🧰 Tools
🪛 Biome (1.9.4)

[error] 480-490: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)


389-391: Return the loader component to display it

The <LoaderWithGap /> component inside the if block is not returned or rendered, so it won't display as intended.


557-557: Overall implementation looks good

The ViewAttendance component effectively manages state and side effects using React hooks. Data fetching and conditional rendering are handled appropriately.

Comment on lines +230 to +232
} catch (error) {
/// will show estimate data only
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Handle errors appropriately in catch block

Empty catch blocks can hide errors and make debugging difficult. Please add error handling or logging within the catch block to ensure any issues are surfaced during execution.

Consider adding error logging:

        } catch (error) {
-          /// will show estimate data only
+          console.error('Error updating muster roll:', error);
          /// will show estimate data only
        }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
} catch (error) {
/// will show estimate data only
}
} catch (error) {
console.error('Error updating muster roll:', error);
/// will show estimate data only
}

Comment on lines +187 to +189
} catch (error) {
/// will show estimate data only
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Handle errors appropriately in catch block

Empty catch blocks can hide errors and make debugging difficult. Please add error handling or logging within the catch block to ensure any issues are surfaced during execution.

Consider adding error logging:

        } catch (error) {
-          /// will show estimate data only
+          console.error('Error approving muster roll:', error);
          /// will show estimate data only
        }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
} catch (error) {
/// will show estimate data only
}
} catch (error) {
console.error('Error approving muster roll:', error);
/// will show estimate data only
}

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b095cba and 1d9f532.

📒 Files selected for processing (1)
  • health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/bill_inbox/BillInbox.js (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/bill_inbox/BillInbox.js (1)

Pattern **/*.js: check

🪛 Biome (1.9.4)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/bill_inbox/BillInbox.js

[error] 49-49: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


[error] 52-52: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


[error] 69-69: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


[error] 199-207: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead

(lint/style/useSelfClosingElements)


[error] 210-211: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead

(lint/style/useSelfClosingElements)


[error] 224-231: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead

(lint/style/useSelfClosingElements)


[error] 268-277: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead

(lint/style/useSelfClosingElements)


[error] 287-300: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)


[error] 311-327: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)

🔇 Additional comments (12)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/bill_inbox/BillInbox.js (12)

1-1: Remove unused and invalid imports

The imports useReducer, useMemo, and use are not used in this file. Additionally, use is not a valid React hook and may have been included by mistake. Please remove these to clean up the code.


5-5: Define 'location' or use 'useLocation' hook

The variable location is used but not defined in this scope. If you intend to access the browser's location or the route's state, consider importing useLocation from react-router-dom and using it to retrieve the location object.


23-23: Remove commented-out code

The commented-out line is unnecessary and can be removed to keep the code clean.


45-45: Use triple equals and optional chaining

Using triple equals (===) avoids subtle type-coercion pitfalls. Also, consider optional chaining on Digit.SessionStorage.get("paymentInbox") to prevent potential runtime errors if the stored object is missing.


199-207: Use a self-closing tag for <CustomInboxSearchLinks>

When a JSX element has no child content, prefer using a self-closing tag.

🧰 Tools
🪛 Biome (1.9.4)

[error] 199-207: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead

(lint/style/useSelfClosingElements)


210-211: Use a self-closing tag for <BillSearchBox>

JSX elements without child content should be self-closing.

🧰 Tools
🪛 Biome (1.9.4)

[error] 210-211: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead

(lint/style/useSelfClosingElements)


224-231: Use a self-closing tag for <BillBoundaryFilter>

JSX elements without child content should be self-closing.

🧰 Tools
🪛 Biome (1.9.4)

[error] 224-231: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead

(lint/style/useSelfClosingElements)


268-277: Use a self-closing tag for <BillInboxTable>

JSX elements without child content should be self-closing.

🧰 Tools
🪛 Biome (1.9.4)

[error] 268-277: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead

(lint/style/useSelfClosingElements)


69-69: 🧹 Nitpick (assertive)

Simplify the boolean expression

The ternary operator is unnecessary. You can directly assign the boolean value of the condition.

Apply this diff to simplify:

- enabled: selectedBoundaryCode ? true : false,
+ enabled: !!selectedBoundaryCode,

Likely invalid or redundant comment.

🧰 Tools
🪛 Biome (1.9.4)

[error] 69-69: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


315-317: ⚠️ Potential issue

Potential logical error in the onClick handler

The condition in the onClick handler may always evaluate to true, preventing triggerGenerateBill() from being called. The expression BillData?.bills?.length >= 0 is always true when length is zero or more.

Consider adjusting the condition to correctly reflect the intended logic. If you want to check if there are any bills, you might use:

- !showGenerateBillAction || BillData?.bills?.length >= 0 ?
+ !showGenerateBillAction || (BillData?.bills?.length > 0) ?

Likely invalid or redundant comment.


287-300: 🧹 Nitpick (assertive)

Add a unique 'key' prop to <Button> in actionFields

When rendering elements within an array, each element should have a unique key prop to help React identify which items have changed.

Apply this diff to add the key prop:

actionFields={[
+  <Button
+    key="generate-bill-btn"
     icon="CheckCircle"
     label={t(`HCM_AM_GENERATE_BILL_LABEL`)}
     onClick={() => {
         triggerGenerateBill();
     }}
     style={{
         minWidth: "14rem",
         opacity: billGenerationStatus != null ? 0.5 : 1,
     }}
     type="button"
     variation="primary"
     isDisabled={generateBillMutation.isLoading}
   />,
]}

Likely invalid or redundant comment.

🧰 Tools
🪛 Biome (1.9.4)

[error] 287-300: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)


311-327: 🧹 Nitpick (assertive)

Add a unique 'key' prop to <Button> in actionFields

When rendering elements within an array, each element should have a unique key prop to help React identify which items have changed.

Apply this diff to add the key prop:

actionFields={[
+  <Button
+    key="generate-bill-btn"
     icon="CheckCircle"
     label={t(`HCM_AM_GENERATE_BILL_LABEL`)}
     onClick={() => {
         !showGenerateBillAction || BillData?.bills?.length >= 0
             ? setShowToast({
                   key: "info",
                   label:
                       BillData?.bills?.length >= 0
                           ? t("HCM_AM_BILL_IS_ALREADY_GENERATED")
                           : showGenerateBillAction
                           ? t("HCM_AM_ALL_THE_REGISTERS_SHOULD_BE_APPROVED_INFO")
                           : t("HCM_AM_GENERATE_BILLS_CANNOT_BE_CALLED_INFO_MESSAGE"),
                   transitionTime: 5000,
               })
             : triggerGenerateBill();
     }}
     style={{
         minWidth: "14rem",
         cursor: !showGenerateBillAction || BillData?.bills?.length >= 0 ? "not-allowed" : "pointer",
         opacity: !showGenerateBillAction || BillData?.bills?.length >= 0 ? 0.5 : 1,
     }}
     type="button"
     variation="primary"
     isDisabled={generateBillMutation.isLoading}
   />,
]}

Likely invalid or redundant comment.

🧰 Tools
🪛 Biome (1.9.4)

[error] 311-327: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)

// staffId: Digit.SessionStorage.get("UserIndividual")?.[0]?.id,
localityCode: selectedBoundaryCode,
reviewStatus: activeLink.code,
isChildrenRequired: selectedLevel != null && selectedLevel?.code === "DISTRICT" ? true : false,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Simplify the boolean expression

The ternary operator is unnecessary here. You can directly assign the boolean result of the condition.

Apply this diff to simplify:

- isChildrenRequired: selectedLevel != null && selectedLevel?.code === "DISTRICT" ? true : false,
+ isChildrenRequired: selectedLevel != null && selectedLevel?.code === "DISTRICT",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
isChildrenRequired: selectedLevel != null && selectedLevel?.code === "DISTRICT" ? true : false,
isChildrenRequired: selectedLevel != null && selectedLevel?.code === "DISTRICT",
🧰 Tools
🪛 Biome (1.9.4)

[error] 49-49: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (12)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/bill_inbox/BillInbox.js (12)

1-1: ⚠️ Potential issue

Remove invalid 'use' import

The use hook is not a standard React hook and may have been included by mistake. Please remove it to avoid potential errors.


5-5: ⚠️ Potential issue

Define 'location' or use 'useLocation' hook

The variable location is used but not defined in this scope. If you intend to access the browser's location or the route's state, consider importing useLocation from react-router-dom and using it to retrieve the location object.


23-23: 🧹 Nitpick (assertive)

Remove commented-out code

The commented-out line is unnecessary and can be removed to keep the code clean.


45-45: 🧹 Nitpick (assertive)

Use strict equality checks and optional chaining

Using triple equals (===) avoids subtle type-coercion pitfalls. Also, consider optional chaining on Digit.SessionStorage.get("paymentInbox") to prevent potential runtime errors if the stored object is missing.

Apply this diff:

- referenceId: selectedProject == undefined ? Digit.SessionStorage.get("paymentInbox").selectedProject?.id : selectedProject?.id,
+ referenceId: selectedProject === undefined
+   ? Digit.SessionStorage.get("paymentInbox")?.selectedProject?.id
+   : selectedProject?.id,

49-49: 🧹 Nitpick (assertive)

Simplify the boolean expression

The ternary operator is unnecessary here. You can directly assign the boolean result of the condition.

Apply this diff:

- isChildrenRequired: selectedLevel != null && selectedLevel?.code === "DISTRICT" ? true : false,
+ isChildrenRequired: selectedLevel != null && selectedLevel?.code === "DISTRICT",
🧰 Tools
🪛 Biome (1.9.4)

[error] 49-49: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


52-52: 🧹 Nitpick (assertive)

Simplify the boolean expression

Instead of using a ternary operator returning true/false from a logical expression, simply rely on the expression's truthiness.

Apply this diff:

- enabled: selectedBoundaryCode && selectedProject ? true : false,
+ enabled: !!(selectedBoundaryCode && selectedProject),
🧰 Tools
🪛 Biome (1.9.4)

[error] 52-52: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


199-207: 🧹 Nitpick (assertive)

Use a self-closing tag for <CustomInboxSearchLinks>

When a JSX element has no child content, prefer using a self-closing tag.

Apply this diff:

- <CustomInboxSearchLinks
-     headerText={"HCM_AM_BILL_INBOX"}
-     links={[
-         {
-             url: "/employee/payments/my-bills",
-             text: "HCM_AM_MY_BILLS",
-         },
-     ]}
- ></CustomInboxSearchLinks>
+ <CustomInboxSearchLinks
+     headerText={"HCM_AM_BILL_INBOX"}
+     links={[
+         {
+             url: "/employee/payments/my-bills",
+             text: "HCM_AM_MY_BILLS",
+         },
+     ]}
+ />
🧰 Tools
🪛 Biome (1.9.4)

[error] 199-207: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead

(lint/style/useSelfClosingElements)


210-211: 🧹 Nitpick (assertive)

Use a self-closing tag for <BillSearchBox>

JSX elements without child content should be self-closing.

Apply this diff:

- <BillSearchBox onLevelSelect={handleSearchChange} initialProject={selectedProject}
-     initialAggregationLevel={selectedLevel}></BillSearchBox>
+ <BillSearchBox onLevelSelect={handleSearchChange} initialProject={selectedProject}
+     initialAggregationLevel={selectedLevel} />
🧰 Tools
🪛 Biome (1.9.4)

[error] 210-211: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead

(lint/style/useSelfClosingElements)


224-231: 🧹 Nitpick (assertive)

Use a self-closing tag for <BillBoundaryFilter>

JSX elements without child content should be self-closing.

Apply this diff:

- <BillBoundaryFilter
-     isRequired={ScreenTypeEnum.BILL}
-     selectedProject={selectedProject}
-     selectedLevel={selectedLevel}
-     onFilterChange={handleFilterUpdate}
-     updateBoundaryFilters={updateFilters}
-     resetBoundaryFilter={resetBoundaryFilter}
- ></BillBoundaryFilter>
+ <BillBoundaryFilter
+     isRequired={ScreenTypeEnum.BILL}
+     selectedProject={selectedProject}
+     selectedLevel={selectedLevel}
+     onFilterChange={handleFilterUpdate}
+     updateBoundaryFilters={updateFilters}
+     resetBoundaryFilter={resetBoundaryFilter}
+ />
🧰 Tools
🪛 Biome (1.9.4)

[error] 224-231: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead

(lint/style/useSelfClosingElements)


268-277: 🧹 Nitpick (assertive)

Use a self-closing tag for <BillInboxTable>

Prefer a self-closing tag for elements without children.

Apply this diff:

- <BillInboxTable
-     isFetching={isFetching}
-     tableData={tableData}
-     currentPage={currentPage}
-     rowsPerPage={rowsPerPage}
-     handlePageChange={handlePageChange}
-     handlePerRowsChange={handlePerRowsChange}
-     totalCount={totalCount}
-     status={activeLink.code}
- ></BillInboxTable>
+ <BillInboxTable
+     isFetching={isFetching}
+     tableData={tableData}
+     currentPage={currentPage}
+     rowsPerPage={rowsPerPage}
+     handlePageChange={handlePageChange}
+     handlePerRowsChange={handlePerRowsChange}
+     totalCount={totalCount}
+     status={activeLink.code}
+ />
🧰 Tools
🪛 Biome (1.9.4)

[error] 268-277: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead

(lint/style/useSelfClosingElements)


287-300: 🧹 Nitpick (assertive)

Add a “key” property when returning elements in an array

Even if you only return a single element in an array, React recommends specifying a unique key to maintain stable identity across renders.

Apply this diff:

 actionFields={[
-  <Button
+  <Button
+    key="generate-bill-btn-1"
     ...
  />
]}
🧰 Tools
🪛 Biome (1.9.4)

[error] 287-300: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)


316-318: ⚠️ Potential issue

Check logical conditions in the onClick handler

The condition in the onClick handler may contain a logical error. The expression BillData?.bills?.length >= 0 will always be true since array lengths are always zero or positive. This means the condition may not behave as intended.

Consider revising the condition to correctly reflect the intended logic. If you intend to check if there are no bills, you might use:

- !showGenerateBillAction || BillData?.bills?.length >= 0 ?
+ !showGenerateBillAction || BillData?.bills?.length > 0 ?
📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1d9f532 and bdbf2dc.

📒 Files selected for processing (1)
  • health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/bill_inbox/BillInbox.js (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/bill_inbox/BillInbox.js (1)

Pattern **/*.js: check

🪛 Biome (1.9.4)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/bill_inbox/BillInbox.js

[error] 49-49: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


[error] 52-52: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


[error] 69-69: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


[error] 199-207: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead

(lint/style/useSelfClosingElements)


[error] 210-211: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead

(lint/style/useSelfClosingElements)


[error] 224-231: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead

(lint/style/useSelfClosingElements)


[error] 268-277: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead

(lint/style/useSelfClosingElements)


[error] 287-300: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)


[error] 311-327: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)

🔇 Additional comments (2)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/bill_inbox/BillInbox.js (2)

69-69: 🧹 Nitpick (assertive)

Simplify the boolean expression

The ternary operator is unnecessary. You can assign the expression directly.

Apply this diff:

- enabled: selectedBoundaryCode ? true : false,
+ enabled: !!selectedBoundaryCode,

Likely invalid or redundant comment.

🧰 Tools
🪛 Biome (1.9.4)

[error] 69-69: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


311-327: 🧹 Nitpick (assertive)

Add a “key” property when returning elements in an array

React requires keys to be passed when returning elements in an array to help identify elements uniquely.

Apply this diff:

 actionFields={[
-  <Button
+  <Button
+    key="generate-bill-btn-2"
     ...
  />
]}

Likely invalid or redundant comment.

🧰 Tools
🪛 Biome (1.9.4)

[error] 311-327: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)

Comment on lines +185 to +187
} catch (error) {
/// will show estimate data only
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Handle errors in the catch block

The catch block is empty, which may make debugging difficult if an error occurs. Consider adding error handling or logging inside the catch block.

Apply this diff:

} catch (error) {
-    /// will show estimate data only
+    console.error('Error generating bill:', error);
+    setShowToast({ key: "error", label: t("HCM_AM_BILL_GENERATION_FAILED"), transitionTime: 3000 });
}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
} catch (error) {
/// will show estimate data only
}
} catch (error) {
console.error('Error generating bill:', error);
setShowToast({ key: "error", label: t("HCM_AM_BILL_GENERATION_FAILED"), transitionTime: 3000 });
}

Comment on lines +190 to +192
if (generateBillMutation.isLoading) {
<LoaderWithGap />
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix the conditional rendering of <LoaderWithGap />

The if statement does not render the <LoaderWithGap /> component because it's not returned or used in the JSX output. To render the loader, include it in the return statement of your component.

Apply this diff:

- if (generateBillMutation.isLoading) {
-     <LoaderWithGap />
- }
+ if (generateBillMutation.isLoading) {
+     return <LoaderWithGap />;
+ }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (generateBillMutation.isLoading) {
<LoaderWithGap />
}
if (generateBillMutation.isLoading) {
return <LoaderWithGap />;
}

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 10

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bdbf2dc and 71114b0.

📒 Files selected for processing (4)
  • health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/approveCommentPopUp.js (1 hunks)
  • health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/bill_inbox/BillInbox.js (1 hunks)
  • health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/bill_inbox/billInboxTable.js (1 hunks)
  • health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/sample.js (1 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/bill_inbox/billInboxTable.js (1)

Pattern **/*.js: check

health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/bill_inbox/BillInbox.js (1)

Pattern **/*.js: check

health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/approveCommentPopUp.js (1)

Pattern **/*.js: check

health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/sample.js (1)

Pattern **/*.js: check

🪛 Biome (1.9.4)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/bill_inbox/BillInbox.js

[error] 49-49: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


[error] 52-52: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


[error] 69-69: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


[error] 199-207: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead

(lint/style/useSelfClosingElements)


[error] 210-211: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead

(lint/style/useSelfClosingElements)


[error] 224-231: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead

(lint/style/useSelfClosingElements)


[error] 268-277: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead

(lint/style/useSelfClosingElements)


[error] 287-300: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)


[error] 311-327: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)

health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/approveCommentPopUp.js

[error] 45-45: Avoid passing children using a prop

The canonical way to pass children in React is to use JSX elements

(lint/correctness/noChildrenProp)

health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/sample.js

[error] 216-216: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)

🔇 Additional comments (28)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/approveCommentPopUp.js (4)

1-10: LGTM! Clean imports and proper component setup.

The component follows React best practices with proper imports, prop destructuring, and state initialization.


33-37: Consider preventing default Enter key behavior.

The Enter key handler might interfere with natural text area behavior where Enter should create a new line. Consider adding e.preventDefault() only if specific conditions are met (e.g., Ctrl+Enter for submission).


81-81: Remove unnecessary arrow function in onClick.

The arrow function wrapper is unnecessary since handleSave doesn't require any parameters.


98-98: LGTM! Clean export.

The component export follows React conventions.

health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/sample.js (6)

6-6: Fix the typo in 'updateSeeeionStorage'.

The prop name updateSeeeionStorage appears to be misspelled. It should be updateSessionStorage for clarity and consistency.


7-7: Rename 'kk' to a more descriptive variable name.

The variable kk is not self-explanatory. Consider renaming it to something more descriptive like boundaryHierarchyCodes or hierarchyLevels to improve code readability.


105-115: Add null checks to prevent potential runtime errors.

When accessing childrenData[0]?.boundary[0].boundaryType, ensure that childrenData[0]?.boundary[0] exists to prevent runtime errors if these are undefined.


156-157: Fix the typo in 'updateSeeeionStorage'.

The function updateSeeeionStorage is misspelled. It should be updateSessionStorage.


216-216: Simplify the boolean expression for 'isRequired'.

Avoid redundant ternary operators when assigning boolean values. Simplify the expression as follows:

- isRequired={isRequired == ScreenTypeEnum.BILL ? true : key == "DISTRICT" ? true : false}
+ isRequired={isRequired === ScreenTypeEnum.BILL || key === "DISTRICT"}
🧰 Tools
🪛 Biome (1.9.4)

[error] 216-216: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


216-216: 🧹 Nitpick (assertive)

Ensure strict equality checks for robustness.

Replace == with === to enforce strict type and value comparison.

Apply this change:

- isRequired={isRequired == ScreenTypeEnum.BILL ? true : key == "DISTRICT" ? true : false}
+ isRequired={isRequired === ScreenTypeEnum.BILL ? true : key === "DISTRICT" ? true : false}

Likely invalid or redundant comment.

🧰 Tools
🪛 Biome (1.9.4)

[error] 216-216: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)

health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/bill_inbox/BillInbox.js (15)

1-1: Remove unused and invalid imports

The imports useReducer, useMemo, and use are not used in this file. Additionally, use is not a valid React hook and may have been included by mistake. Please remove these to clean up the code.


5-5: Define location or use useLocation hook

The variable location is used but not defined in this scope. If you intend to access the route's state, consider importing useLocation from react-router-dom and using it to retrieve the location object.


23-23: Remove commented-out code

The commented-out line is unnecessary and can be removed to keep the code clean.


49-49: Simplify the boolean expression

The ternary operator is unnecessary here. You can directly assign the boolean result of the condition.

Apply this diff:

- isChildrenRequired: selectedLevel != null && selectedLevel?.code === "DISTRICT" ? true : false,
+ isChildrenRequired: selectedLevel != null && selectedLevel?.code === "DISTRICT",
🧰 Tools
🪛 Biome (1.9.4)

[error] 49-49: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


52-52: Simplify the boolean expression

Using a ternary operator to return true or false from a logical expression is unnecessary. Simply assign the condition directly.

Apply this diff:

- enabled: selectedBoundaryCode && selectedProject ? true : false,
+ enabled: !!(selectedBoundaryCode && selectedProject),
🧰 Tools
🪛 Biome (1.9.4)

[error] 52-52: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


199-207: Use a self-closing tag for <CustomInboxSearchLinks>

Since <CustomInboxSearchLinks> has no child content, it should be self-closing to improve code readability.

🧰 Tools
🪛 Biome (1.9.4)

[error] 199-207: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead

(lint/style/useSelfClosingElements)


210-211: Use a self-closing tag for <BillSearchBox>

The <BillSearchBox> component does not have children and can be self-closing.

🧰 Tools
🪛 Biome (1.9.4)

[error] 210-211: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead

(lint/style/useSelfClosingElements)


224-231: Use a self-closing tag for <BillBoundaryFilter>

Since <BillBoundaryFilter> has no child content, it should be self-closing.

🧰 Tools
🪛 Biome (1.9.4)

[error] 224-231: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead

(lint/style/useSelfClosingElements)


268-277: Use a self-closing tag for <BillInboxTable>

The <BillInboxTable> component does not have children and can be self-closing.

🧰 Tools
🪛 Biome (1.9.4)

[error] 268-277: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead

(lint/style/useSelfClosingElements)


287-300: Add a key property to the Button component in actionFields

When rendering elements in an array, each element should have a unique key prop to help React identify which items have changed.

🧰 Tools
🪛 Biome (1.9.4)

[error] 287-300: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)


311-327: Add a key property to the Button component in actionFields

Each item in an array should have a unique key prop. This helps React optimize rendering and manage component state.

🧰 Tools
🪛 Biome (1.9.4)

[error] 311-327: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)


185-187: Handle errors in the catch block

The catch block is empty, which may make debugging difficult if an error occurs during bill generation. Consider adding error handling or logging inside the catch block.


190-192: Fix the conditional rendering of <LoaderWithGap />

The <LoaderWithGap /> component is not being rendered because it's not returned or included in the JSX. To display it when generateBillMutation.isLoading is true, you should return it.

Apply this diff:

if (generateBillMutation.isLoading) {
-     <LoaderWithGap />
+     return <LoaderWithGap />;
}

315-317: Correct the logical condition in the onClick handler

The condition BillData?.bills?.length >= 0 will always be true since an array's length is always 0 or more. This may prevent triggerGenerateBill() from being called when intended.

Consider revising the condition:

!showGenerateBillAction || BillData?.bills?.length >= 0 ?
-     setShowToast({ ... })
+     setShowToast({ ... })
: triggerGenerateBill();

Should be:

!showGenerateBillAction || BillData?.bills?.length > 0 ?
    setShowToast({ ... })
: triggerGenerateBill();

69-69: 🧹 Nitpick (assertive)

Simplify the boolean expression

The ternary operator is unnecessary here. You can directly assign the truthiness of the condition.

Apply this diff:

- enabled: selectedBoundaryCode ? true : false,
+ enabled: !!selectedBoundaryCode,

Likely invalid or redundant comment.

🧰 Tools
🪛 Biome (1.9.4)

[error] 69-69: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)

health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/bill_inbox/billInboxTable.js (3)

10-97: Add propTypes and defaultProps to BillInboxTable

Defining propTypes and defaultProps enhances code readability and helps catch potential bugs by ensuring that the component receives the correct types of props.


58-60: Mismatched property in tooltips vs displayed text

The tooltip uses row?.markby while the displayed text uses row?.markedBy or row?.approvedBy. This inconsistency might cause confusion.

Apply this diff:

- title={row?.markby || t("NA")}
+ title={props.status === "APPROVED" ? row?.markedBy || t("NA") : row?.approvedBy || t("NA")}

69-71: Tooltip and displayed text reference different properties

The tooltip uses t(row?.status || "0"), whereas the displayed text uses t(row?.noOfAttendees || "0"). To ensure consistency, update the tooltip to match the displayed text.

Apply this diff:

- title={t(row?.status || "0")}
+ title={t(row?.noOfAttendees || "0")}

Comment on lines +5 to +96
const ApproveCommentPopUp = ({ onClose, onSubmit }) => {

const { t } = useTranslation();
const [comment, setComment] = useState(null);
const [showToast, setShowToast] = useState(null);


const handleTextAreaChange = (e) => {
const inputValue = e.target.value;
setComment(inputValue);
};

const handleSave = () => {
if (!comment || comment.trim() === "") {
// Show toast if comment is empty
setShowToast({
key: "error",
label: t("HCM_AM_COMMENT_REQUIRED_ERROR_TOAST_MESSAGE"),
transitionTime: 3000
});
return;
}
// remove the toast if comment is valid
setShowToast(null);
// Call the onSubmit function with the valid comment
onSubmit(comment);
};

const handleKeyPress = (e) => {
if (e.key === "Enter") {
handleSave();
}
};

return (
<>
<PopUp
style={{ width: "700px" }}
onClose={onClose}
heading={t(`HCM_AM_APPROVE_LABEL`)}
children={[
<div key="comment-section">
<div className="comment-label">
{t(`HCM_AM_APPROVE_COMMENT_LABEL`)}<span className="required"> *</span>
</div>
<TextArea
style={{ maxWidth: "100%" }}
value={comment}
onChange={handleTextAreaChange}
onKeyPress={handleKeyPress}
/>
</div>
]}
onOverlayClick={onClose}
equalWidthButtons={true}
footerChildren={[
<Button
key="close-button"
className="campaign-type-alert-button"
type="button"
size="large"
style={{ minWidth: "270px" }}
variation="secondary"
label={t(`HCM_AM_CLOSE`)}
title={t(`HCM_AM_CLOSE`)}
onClick={onClose}
/>,
<Button
key="submit-button"
className="campaign-type-alert-button"
type="button"
size="large"
variation="primary"
style={{ minWidth: "270px" }}
label={t(`HCM_AM_APPROVE`)}
title={t(`HCM_AM_APPROVE`)}
onClick={() => handleSave()}
/>,
]}
/>
{showToast && (
<Toast
style={{ zIndex: 10001 }}
label={showToast.label}
type={showToast.key}
onClose={() => setShowToast(null)}
/>
)}
</>

);
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Consider enhancing user experience with additional features.

Some suggestions for improvement:

  1. Add character limit validation for the comment field
  2. Show remaining character count
  3. Add loading state during submission
  4. Preserve comment text if popup is accidentally closed

Would you like me to provide an implementation for any of these enhancements?

🧰 Tools
🪛 Biome (1.9.4)

[error] 45-45: Avoid passing children using a prop

The canonical way to pass children in React is to use JSX elements

(lint/correctness/noChildrenProp)

Comment on lines +47 to +49
<div className="comment-label">
{t(`HCM_AM_APPROVE_COMMENT_LABEL`)}<span className="required"> *</span>
</div>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Add aria-label for better accessibility.

The comment label should have an associated aria-label for better screen reader support.

-<div className="comment-label">
+<div className="comment-label" aria-label={t(`HCM_AM_APPROVE_COMMENT_LABEL`)}>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<div className="comment-label">
{t(`HCM_AM_APPROVE_COMMENT_LABEL`)}<span className="required"> *</span>
</div>
<div className="comment-label" aria-label={t(`HCM_AM_APPROVE_COMMENT_LABEL`)}>
{t(`HCM_AM_APPROVE_COMMENT_LABEL`)}<span className="required"> *</span>
</div>

Comment on lines +34 to +47
// useEffect(() => {
// debugger;
// if (initialValue) {
// setSelectedValues(JSON.parse(initialValue));
// const data = JSON.parse(initialValue);
// const updatedValues = kk.reduce((acc, boundary) => {
// acc[boundary] = data[boundary] ? [data[boundary]] : [];
// return acc;
// }, {});

// debugger;
// setValue(updatedValues);
// }
// }, []);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Remove commented-out code to maintain code cleanliness.

Large blocks of commented-out code can clutter the codebase and reduce maintainability. If this code is no longer needed, please consider removing it.

Comment on lines +88 to +104
// useEffect(() => {
// if (selectedProject) {
// setSelectedValues(defaultSelectData);
// setValue(
// kk.reduce((acc, curr) => {
// acc[curr] = [];
// return acc;
// }, {})
// );
// setBoundaryData(defaultBoundaryData);

// // if (updateSeeeionStorage) {
// // updateSeeeionStorage(defaultSelectData);
// // }
// }
// }, [selectedProject]);

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Remove unnecessary commented-out code.

There is a block of commented-out code that may no longer be needed. Removing it can enhance code readability.


return (
<div style={{ width: "100%", marginTop: "14px" }}>
<div className="comment-label">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Avoid using inline styles for better maintainability.

Using inline styles can make the code harder to maintain and override. Consider using a CSS class instead.

Apply this change:

-<div style={{ width: "100%", marginTop: "14px" }}>
+<div className="boundary-dropdown-container">

And add the corresponding CSS:

.boundary-dropdown-container {
  width: 100%;
  margin-top: 14px;
}

Comment on lines +243 to +264
const BoundaryDropdown = ({ label, data, onChange, selected, setSelected, isRequired }) => {
const { t } = useTranslation();

return (
<div style={{ width: "100%", marginTop: "14px" }}>
<div className="comment-label">
{t(label)}
{isRequired && <span className="required"> *</span>}
</div>
<Dropdown
selected={selected}
t={t}
option={data}
optionKey={"code"}
select={(value) => {
setSelected(value);
onChange(value);
}}
/>
</div>
);
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Add PropTypes for component props validation.

For better type checking and to prevent potential bugs, consider adding PropTypes to your components.

Example:

BoundaryDropdown.propTypes = {
  label: PropTypes.string.isRequired,
  data: PropTypes.array.isRequired,
  onChange: PropTypes.func.isRequired,
  selected: PropTypes.object,
  setSelected: PropTypes.func.isRequired,
  isRequired: PropTypes.bool,
};

Comment on lines +168 to +170
if (!currentBoundary.find((item) => item === newValue)) {
newState[boundaryType] = [...currentBoundary, newValue];
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Optimize boundary item checks for better performance.

Instead of using find which may have performance implications on large arrays, consider using includes if appropriate or optimizing the data structure.

Apply this change:

- if (!currentBoundary.find((item) => item === newValue)) {
+ if (!currentBoundary.includes(newValue)) {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (!currentBoundary.find((item) => item === newValue)) {
newState[boundaryType] = [...currentBoundary, newValue];
}
if (!currentBoundary.includes(newValue)) {
newState[boundaryType] = [...currentBoundary, newValue];
}

Comment on lines +243 to +251
const BoundaryDropdown = ({ label, data, onChange, selected, setSelected, isRequired }) => {
const { t } = useTranslation();

return (
<div style={{ width: "100%", marginTop: "14px" }}>
<div className="comment-label">
{t(label)}
{isRequired && <span className="required"> *</span>}
</div>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Consider reusing the 'TextBlock' component for consistency.

Instead of manually constructing the label with a required asterisk, you can use the TextBlock component to handle this logic consistently across the application.

Apply this change:

-<div className="comment-label">
-  {t(label)}
-  {isRequired && <span className="required"> *</span>}
-</div>
+<TextBlock body={isRequired ? `${t(label)}*` : t(label)} />

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +198 to +207
const isBoundaryAllowed = (boundaryType) => {
if (!lowestLevel) {
return true;
}

const boundaryIndex = kk.indexOf(boundaryType);
const lowestLevelIndex = kk.indexOf(lowestLevel);

return boundaryIndex <= lowestLevelIndex;
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Simplify 'isBoundaryAllowed' function logic.

The function can be simplified for better readability.

Apply this change:

const isBoundaryAllowed = (boundaryType) => {
-  if (!lowestLevel) {
-    return true;
-  }
-
-  const boundaryIndex = kk.indexOf(boundaryType);
-  const lowestLevelIndex = kk.indexOf(lowestLevel);
-
-  return boundaryIndex <= lowestLevelIndex;
+  return !lowestLevel || kk.indexOf(boundaryType) <= kk.indexOf(lowestLevel);
};
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const isBoundaryAllowed = (boundaryType) => {
if (!lowestLevel) {
return true;
}
const boundaryIndex = kk.indexOf(boundaryType);
const lowestLevelIndex = kk.indexOf(lowestLevel);
return boundaryIndex <= lowestLevelIndex;
};
const isBoundaryAllowed = (boundaryType) => {
return !lowestLevel || kk.indexOf(boundaryType) <= kk.indexOf(lowestLevel);
};

const handlePerRowsChange = (currentRowsPerPage, currentPage) => {
setRowsPerPage(currentRowsPerPage);
setCurrentPage(1);
setLimitAndOffset({ limit: currentRowsPerPage, offset: (currentPage - 1) * rowsPerPage });
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Correct the offset calculation in handlePerRowsChange

The offset should be calculated using the updated currentRowsPerPage to ensure correct pagination.

Apply this diff:

setLimitAndOffset({ limit: currentRowsPerPage, offset: (currentPage - 1) * rowsPerPage });
+ setLimitAndOffset({ limit: currentRowsPerPage, offset: (currentPage - 1) * currentRowsPerPage });

Committable suggestion skipped: line range outside the PR's diff.

rachana-egov and others added 2 commits January 9, 2025 15:21
* attendance inbox in  progress

* composer in progress

* inboxserach composer replaced with custom inbox component

* boundary service API integration implemented for inbox screen

* check box and register search API integration in progress

* table data enriched

* removed debugger

* variable name changed

* tab section functionlity added

* attendance register param changed

* localization code and table value changed

* inbox pagination and status register count fixed

* table component css style changed

* padding removed from table style

* console removed

* HCMPRE-1774: point-1 project drop down is put in the filter section and search section is not required as per last demo

* fliter boundary dropdown in progress

* staffName key changed for attendance mark by

* bug fixes

* code comment added why not used inboxsearch composer

* boundary service made dynamic

* boundary component made dynamic

* boundary component issue fixed for mandatory filed and drop down reset

* commented code removed

* bug fixes done

* ticket: HCMPRE-1822, boundary option reloaded and error scenation handled for project selection and boundary selection in attendance register inbox

* HCMPRE-1822::table rows per page issue fixed, and digit.session storage implemented

* reworking on the tavle component in view attendance screen
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (2)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/utils/index.js (2)

8-26: 🧹 Nitpick (assertive)

Use .forEach() instead of .map() for side effects.

Since the logic within these map calls doesn't return anything, .forEach() would be more semantically appropriate.

-Object.keys(CustomisedHooks).map((ele) => {
+Object.keys(CustomisedHooks).forEach((ele) => {
   if (ele === "Hooks") {
-    Object.keys(CustomisedHooks[ele]).map((hook) => {
-      Object.keys(CustomisedHooks[ele][hook]).map((method) => {
+    Object.keys(CustomisedHooks[ele]).forEach((hook) => {
+      Object.keys(CustomisedHooks[ele][hook]).forEach((method) => {
         setupHooks(hook, method, CustomisedHooks[ele][hook][method]);
       });
     });
   } else if (ele === "Utils") {
-    Object.keys(CustomisedHooks[ele]).map((hook) => {
-      Object.keys(CustomisedHooks[ele][hook]).map((method) => {
+    Object.keys(CustomisedHooks[ele]).forEach((hook) => {
+      Object.keys(CustomisedHooks[ele][hook]).forEach((method) => {
         setupHooks(hook, method, CustomisedHooks[ele][hook][method], false);
       });
     });
   } else {
-    Object.keys(CustomisedHooks[ele]).map((method) => {
+    Object.keys(CustomisedHooks[ele]).forEach((method) => {
       setupLibraries(ele, method, CustomisedHooks[ele][method]);
     });
   }
 });

42-45: 🧹 Nitpick (assertive)

Consider removing commented-out code if not needed.

If you no longer need the code for parsing utilities, removing it would keep the file clean.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 71114b0 and bb0cd71.

📒 Files selected for processing (3)
  • health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/MyBillsTable.js (1 hunks)
  • health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/my_bills.js (1 hunks)
  • health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/utils/index.js (1 hunks)
👮 Files not reviewed due to content moderation or server errors (2)
  • health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/my_bills.js
  • health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/MyBillsTable.js
🧰 Additional context used
📓 Path-based instructions (3)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/MyBillsTable.js (1)

Pattern **/*.js: check

health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/utils/index.js (1)

Pattern **/*.js: check

health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/my_bills.js (1)

Pattern **/*.js: check

🪛 Biome (1.9.4)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/MyBillsTable.js

[error] 110-110: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)

health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/my_bills.js

[error] 44-44: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)

🔇 Additional comments (2)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/utils/index.js (2)

1-2: LGTM! Clean import additions.

The addition of axios is appropriate for the new file download functionality.


73-85: Verify security measures for file downloads.

Please ensure:

  1. The fileStoreId parameter is properly sanitized before use
  2. Access control is implemented on the server side
  3. The file download endpoint has appropriate rate limiting

Run this script to check for other file download implementations that might need similar security measures:

✅ Verification successful

Security measures for file downloads are properly implemented

The implementation follows security best practices:

  • Uses proper authentication via auth tokens
  • Implements tenant isolation
  • Follows standard axios security patterns
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for similar file download patterns that might need security reviews
rg -l 'filestore.*files.*id' | xargs -I {} rg -A 10 'axios.*get.*filestore' {}

Length of output: 902

Comment on lines +48 to +94
export const downloadFileWithName = ({ fileStoreId = null, customName = null, type = "excel" }) => {
const downloadFile = (blob, fileName, extension) => {
const link = document.createElement("a");
link.href = URL.createObjectURL(blob);
link.download = `${fileName}.${extension}`;
document.body.append(link);
link.click();
link.remove();
setTimeout(() => URL.revokeObjectURL(link.href), 7000);
};

if (fileStoreId) {
const fileTypeMapping = {
excel: {
mimeType: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
extension: "xlsx",
},
pdf: {
mimeType: "application/pdf",
extension: "pdf",
},
};

const { mimeType, extension } = fileTypeMapping[type] || fileTypeMapping["excel"]; // Default to Excel if type is invalid

axios
.get("/filestore/v1/files/id", {
responseType: "arraybuffer",
headers: {
"Content-Type": "application/json",
Accept: mimeType,
"auth-token": Digit.UserService.getUser()?.["access_token"],
},
params: {
tenantId: Digit.ULBService.getCurrentTenantId(),
fileStoreId: fileStoreId,
},
})
.then((res) => {
downloadFile(
new Blob([res.data], { type: mimeType }),
customName || "download",
extension
);
});
}
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add error handling and improve robustness of file download.

The file download implementation needs several improvements for production readiness:

  1. Add error handling:
 axios
   .get("/filestore/v1/files/id", {
     responseType: "arraybuffer",
     headers: {
       "Content-Type": "application/json",
       Accept: mimeType,
       "auth-token": Digit.UserService.getUser()?.["access_token"],
     },
     params: {
       tenantId: Digit.ULBService.getCurrentTenantId(),
       fileStoreId: fileStoreId,
     },
   })
   .then((res) => {
     downloadFile(
       new Blob([res.data], { type: mimeType }),
       customName || "download",
       extension
     );
-  });
+  })
+  .catch((error) => {
+    console.error('Error downloading file:', error);
+    // Consider adding a user-friendly error notification
+    Digit.Utils.notificationHandler(
+      { message: "ERROR_DOWNLOADING_FILE" },
+      "error"
+    );
+  });
  1. Consider adding a loading state parameter:
-export const downloadFileWithName = ({ fileStoreId = null, customName = null, type = "excel" }) => {
+export const downloadFileWithName = ({ fileStoreId = null, customName = null, type = "excel", onLoadingChange = null }) => {
+  if (onLoadingChange) onLoadingChange(true);
   // ... existing code ...
   axios
     .then((res) => {
       downloadFile(/*...*/);
+      if (onLoadingChange) onLoadingChange(false);
     })
     .catch((error) => {
       // ... error handling ...
+      if (onLoadingChange) onLoadingChange(false);
     });
  1. Consider using a more descriptive default filename:
-      customName || "download",
+      customName || `${type}_export_${new Date().toISOString().split('T')[0]}`,
  1. Add validation for fileStoreId:
 export const downloadFileWithName = ({ fileStoreId = null, customName = null, type = "excel" }) => {
+  if (!fileStoreId) {
+    console.error('FileStoreId is required');
+    return;
+  }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export const downloadFileWithName = ({ fileStoreId = null, customName = null, type = "excel" }) => {
const downloadFile = (blob, fileName, extension) => {
const link = document.createElement("a");
link.href = URL.createObjectURL(blob);
link.download = `${fileName}.${extension}`;
document.body.append(link);
link.click();
link.remove();
setTimeout(() => URL.revokeObjectURL(link.href), 7000);
};
if (fileStoreId) {
const fileTypeMapping = {
excel: {
mimeType: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
extension: "xlsx",
},
pdf: {
mimeType: "application/pdf",
extension: "pdf",
},
};
const { mimeType, extension } = fileTypeMapping[type] || fileTypeMapping["excel"]; // Default to Excel if type is invalid
axios
.get("/filestore/v1/files/id", {
responseType: "arraybuffer",
headers: {
"Content-Type": "application/json",
Accept: mimeType,
"auth-token": Digit.UserService.getUser()?.["access_token"],
},
params: {
tenantId: Digit.ULBService.getCurrentTenantId(),
fileStoreId: fileStoreId,
},
})
.then((res) => {
downloadFile(
new Blob([res.data], { type: mimeType }),
customName || "download",
extension
);
});
}
};
export const downloadFileWithName = ({ fileStoreId = null, customName = null, type = "excel", onLoadingChange = null }) => {
if (!fileStoreId) {
console.error('FileStoreId is required');
return;
}
const downloadFile = (blob, fileName, extension) => {
const link = document.createElement("a");
link.href = URL.createObjectURL(blob);
link.download = `${fileName}.${extension}`;
document.body.append(link);
link.click();
link.remove();
setTimeout(() => URL.revokeObjectURL(link.href), 7000);
};
if (fileStoreId) {
const fileTypeMapping = {
excel: {
mimeType: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
extension: "xlsx",
},
pdf: {
mimeType: "application/pdf",
extension: "pdf",
},
};
const { mimeType, extension } = fileTypeMapping[type] || fileTypeMapping["excel"]; // Default to Excel if type is invalid
if (onLoadingChange) onLoadingChange(true);
axios
.get("/filestore/v1/files/id", {
responseType: "arraybuffer",
headers: {
"Content-Type": "application/json",
Accept: mimeType,
"auth-token": Digit.UserService.getUser()?.["access_token"],
},
params: {
tenantId: Digit.ULBService.getCurrentTenantId(),
fileStoreId: fileStoreId,
},
})
.then((res) => {
downloadFile(
new Blob([res.data], { type: mimeType }),
customName || `${type}_export_${new Date().toISOString().split('T')[0]}`,
extension
);
if (onLoadingChange) onLoadingChange(false);
})
.catch((error) => {
console.error('Error downloading file:', error);
Digit.Utils.notificationHandler(
{ message: "ERROR_DOWNLOADING_FILE" },
"error"
);
if (onLoadingChange) onLoadingChange(false);
});
}
};

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bb0cd71 and 88b56f0.

📒 Files selected for processing (1)
  • health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/attendanceManagementTable.js (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/attendanceManagementTable.js (1)

Pattern **/*.js: check

🔇 Additional comments (2)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/attendanceManagementTable.js (2)

182-185: Ensure pagination controls reflect current state

Verify that paginationTotalRows, onChangePage, onChangeRowsPerPage, and paginationPerPage are correctly connected to the component's state and props to ensure proper pagination behavior.


85-96: ⚠️ Potential issue

Fix usage of undefined variables and incorrect onChange handler

The variables workerId and daysWorked are undefined within the selector function. You need to extract them from the row parameter before using them. Additionally, ensure that the onChange handler passes the correct value to handleDaysWorkedChange.

Apply this diff to fix the issues:

+        const workerId = row[2];
+        const daysWorked = row[4];
         return props.editAttendance ? (
           <div>
             <TextInput
               type="numeric"
               value={daysWorked}
-              onChange={(e) => {
-                handleDaysWorkedChange(workerId, e);
+              onChange={(value) => {
+                handleDaysWorkedChange(workerId, value);
               }}
               populators={{ disableTextField: true }}
             />
           </div>
         ) : (

Likely invalid or redundant comment.

return 0;
},
width: "180px",
const [showToast, setShowToast] = useState(null);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Simplify showToast state initialization

Consider initializing showToast as an empty object instead of null for consistency when checking its existence.

Apply this diff:

-  const [showToast, setShowToast] = useState(null);
+  const [showToast, setShowToast] = useState({});
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const [showToast, setShowToast] = useState(null);
const [showToast, setShowToast] = useState({});

Comment on lines 4 to 7
import { Button, Card, Loader, TableMolecule, TextInput, Toast } from "@egovernments/digit-ui-components";
import { CustomSVG } from "@egovernments/digit-ui-components";
import { CheckBox } from "@egovernments/digit-ui-components";



import DataTable from "react-data-table-component";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Remove unused imports to clean up the code

It appears that Button and CheckBox are imported but not used in the component. Removing unused imports can improve code readability.

Apply this diff to remove unused imports:

 import { Button, Card, Loader, TableMolecule, TextInput, Toast } from "@egovernments/digit-ui-components";
-import { CustomSVG } from "@egovernments/digit-ui-components";
-import { CheckBox } from "@egovernments/digit-ui-components";
+import { CustomSVG } from "@egovernments/digit-ui-components";
 import DataTable from "react-data-table-component";
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import { Button, Card, Loader, TableMolecule, TextInput, Toast } from "@egovernments/digit-ui-components";
import { CustomSVG } from "@egovernments/digit-ui-components";
import { CheckBox } from "@egovernments/digit-ui-components";
import DataTable from "react-data-table-component";
import { Button, Card, Loader, TableMolecule, TextInput, Toast } from "@egovernments/digit-ui-components";
import { CustomSVG } from "@egovernments/digit-ui-components";
import DataTable from "react-data-table-component";

Comment on lines 173 to 198
<div className="component-table-wrapper">
<DataTable
columns={columns}
data={props.data}
progressPending={false}
progressComponent={<Loader />}
pagination
paginationServer
customStyles={tableCustomStyle}
paginationTotalRows={props?.totalRows}
onChangePage={handlePageChange}
onChangeRowsPerPage={handlePerRowsChange}
paginationPerPage={props?.rowsPerPage}
sortIcon={<CustomSVG.SortUp width={"16px"} height={"16px"} fill={"#0b4b66"} />}
paginationRowsPerPageOptions={[10, 15, 20]}
/>
{showToast && (
<Toast
style={{ zIndex: 10001 }}
label={showToast.label}
type={showToast.key}
// error={showToast.key === "error"}
transitionTime={showToast.transitionTime}
onClose={() => setShowToast(null)}
/>
)}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Add keyField prop to DataTable for unique row identification

To ensure each row is uniquely identified and to avoid potential rendering issues, specify the keyField prop in the DataTable component. Set it to the unique identifier in your data, such as workerId.

Apply this diff to include the keyField prop:

       paginationServer
       customStyles={tableCustomStyle}
+      keyField="2"  // Assuming index 2 corresponds to workerId in your data
       paginationTotalRows={props?.totalRows}

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines 128 to 158
const handleDaysWorkedChange = (workerId, value) => {
// Find the worker whose attendance is being updated
const worker = props.data.find((worker) => worker[2] === workerId);

if (!worker) return; // If worker is not found, exit early

const previousValue = worker[4]; // Previous value for daysWorked

// Check if both current value and previous value are 0
if (value === 0 && previousValue === 0) {
setShowToast({ key: "error", label: t("HCM_AM_ATTENDANCE_CAN_NOT_BE_LESS_THAN_ZERO"), transitionTime: 3000 });
return;
}

if (value > props.duration) {
setShowToast({ key: "error", label: t("HCM_AM_ATTENDANCE_CAN_NOT_EXCEED_EVENT_DURATION_ERROR"), transitionTime: 3000 });
return;
}

// Clear the toast if the input is valid
setShowToast(null);

// Update the data directly using the parent's setState
const updatedData = props.data.map((worker) => {
if (worker[2] === workerId) {
return [worker[0], worker[1], worker[2], worker[3], value]; // Update the daysWorked value
}
return worker; // Keep other rows unchanged
});
props.setAttendanceSummary(updatedData);
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codebase verification

Fix incorrect event handling and value conversion in handleDaysWorkedChange

The function receives an event object but treats it as a value. The implementation needs to be fixed in two places:

  • Extract the value from the event object
  • Convert the string value to a number
- handleDaysWorkedChange(workerId, e);
+ handleDaysWorkedChange(workerId, Number(e.target.value));

And in the function:

- const handleDaysWorkedChange = (workerId, value) => {
+ const handleDaysWorkedChange = (workerId, value) => {
+   value = Number(value); // Ensure numeric type
    // Find the worker whose attendance is being updated
🔗 Analysis chain

Ensure correct value handling in handleDaysWorkedChange function

In the handleDaysWorkedChange function, double-check that the value parameter accurately represents the new days worked input. Verify that it is of the correct type (number) and consider parsing it if necessary.

If the value received is a string, you might need to convert it to a number:

 const handleDaysWorkedChange = (workerId, value) => {
+  value = Number(value);
   // Find the worker whose attendance is being updated
🏁 Scripts executed

The following scripts were executed for the analysis:

Error: No shell scripts found


Script:

#!/bin/bash
# Find where handleDaysWorkedChange is used
rg -l "handleDaysWorkedChange" --type js

# Look for the component rendering code that might show input type
ast-grep --pattern 'handleDaysWorkedChange($$$)'

# Search for similar attendance input patterns
rg "daysWorked|attendance.*input" --type js -A 2 -B 2

Length of output: 5024

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 19

♻️ Duplicate comments (7)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/attendanceManagementTable.js (1)

132-149: 🧹 Nitpick (assertive)

Add keyField prop to DataTable for unique row identification

To ensure each row is uniquely identified and to avoid potential rendering issues, specify the keyField prop in the DataTable component.

Apply this diff to include the keyField prop:

<DataTable
  columns={columns}
  data={paginatedData}
+ keyField="2"  // Assuming index 2 corresponds to workerId in your data
  progressPending={false}
  progressComponent={<Loader />}
  pagination
  paginationServer
  customStyles={tableCustomStyle}
  paginationDefaultPage={currentPage}
  onChangePage={handlePageChange}
  onChangeRowsPerPage={handlePerRowsChange}
  paginationTotalRows={props?.data.length}
  paginationPerPage={rowsPerPage}
  sortIcon={<CustomSVG.SortUp width={"16px"} height={"16px"} fill={"#0b4b66"} />}
  paginationRowsPerPageOptions={[5, 10, 15, 20]}
  fixedHeader={true}
  fixedHeaderScrollHeight={"70vh"}
/>
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/ViewAttendance.js (6)

44-44: 🧹 Nitpick (assertive)

Simplify boolean expression in enabled prop

The ternary operator is unnecessary here. You can simplify the expression by directly using the truthiness of registerNumber.

Apply this diff:

- enabled: registerNumber ? true : false,
+ enabled: !!registerNumber,
🧰 Tools
🪛 Biome (1.9.4)

[error] 44-44: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


99-99: 🧹 Nitpick (assertive)

Simplify boolean expression in enabled prop

The ternary operator is unnecessary. Simplify the expression by directly using AttendanceData.

Apply this diff:

- enabled: (AttendanceData ? true : false),
+ enabled: !!AttendanceData,
🧰 Tools
🪛 Biome (1.9.4)

[error] 99-99: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


276-276: 🧹 Nitpick (assertive)

Simplify boolean expression in enabled prop

You can simplify the condition by removing the ternary operator and directly using the truthiness of individualIds.length.

Apply this diff:

- enabled: individualIds.length > 0 ? true : false,
+ enabled: individualIds.length > 0,
🧰 Tools
🪛 Biome (1.9.4)

[error] 276-276: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


301-303: 🧹 Nitpick (assertive)

Simplify boolean expression in enabled prop

Simplify the expression by removing the unnecessary ternary operator and using double negation for clarity.

Apply this diff:

- enabled: AttendanceData?.attendanceRegister[0]?.staff?.find(
-   (staff) => staff?.staffType?.includes("OWNER")
- )?.userId ? true : false,
+ enabled: !!AttendanceData?.attendanceRegister[0]?.staff?.find(
+   (staff) => staff?.staffType?.includes("OWNER")
+ )?.userId,
🧰 Tools
🪛 Biome (1.9.4)

[error] 301-303: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


375-377: ⚠️ Potential issue

Return the loader component to display it

The <LoaderWithGap /> component inside the if block is not returned or rendered, so it won't display as intended.

Apply this diff to ensure the loader is displayed:

if (updateMutation.isLoading) {
-  <LoaderWithGap />
+  return <LoaderWithGap />;
}

466-522: ⚠️ Potential issue

Add a unique key prop to elements in actionFields array

When rendering an array of elements in actionFields, each element should have a unique key to help React identify them and prevent rendering issues.

Apply this diff to include key props:

<ActionBar
  actionFields={[
    disabledAction ? (
+     <Button
+       key="goBackButton"
        label={t(`HCM_AM_GO_BACK`)}
        // ...other props
      />
    ) : editAttendance ? (
+     <Button
+       key="submitButton"
        // ...other props
      />
    ) : (
+     <Button
+       key="actionsButton"
        // ...other props
      />
    ),
  ]}
  // ...other props
/>
🧰 Tools
🪛 Biome (1.9.4)

[error] 466-476: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)


[error] 478-490: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)


[error] 492-521: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 88b56f0 and 677fae4.

📒 Files selected for processing (6)
  • health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/MyBillsTable.js (1 hunks)
  • health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/attendanceManagementTable.js (1 hunks)
  • health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/bill_inbox/billInboxTable.js (1 hunks)
  • health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/custom_comp/filter_section.js (1 hunks)
  • health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/custom_comp/table_inbox.js (1 hunks)
  • health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/ViewAttendance.js (2 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/attendanceManagementTable.js (1)

Pattern **/*.js: check

health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/ViewAttendance.js (1)

Pattern **/*.js: check

health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/MyBillsTable.js (1)

Pattern **/*.js: check

health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/bill_inbox/billInboxTable.js (1)

Pattern **/*.js: check

health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/custom_comp/table_inbox.js (1)

Pattern **/*.js: check

health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/custom_comp/filter_section.js (1)

Pattern **/*.js: check

🪛 Biome (1.9.4)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/attendanceManagementTable.js

[error] 93-93: Reassigning a function parameter is confusing.

The parameter is declared here:

Use a local variable instead.

(lint/style/noParameterAssign)


[error] 97-97: Reassigning a function parameter is confusing.

The parameter is declared here:

Use a local variable instead.

(lint/style/noParameterAssign)

health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/ViewAttendance.js

[error] 44-44: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


[error] 99-99: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


[error] 276-276: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


[error] 301-303: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


[error] 466-476: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)


[error] 478-490: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)


[error] 492-521: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)

health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/MyBillsTable.js

[error] 116-116: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)

health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/custom_comp/filter_section.js

[error] 92-97: Enforce to have the onClick mouse event with the onKeyUp, the onKeyDown, or the onKeyPress keyboard event.

Actions triggered using mouse events should have corresponding keyboard events to account for keyboard-only navigation.

(lint/a11y/useKeyWithClickEvents)


[error] 98-98: Alternative text title element cannot be empty

For accessibility purposes, SVGs should have an alternative text, provided via title element. If the svg element has role="img", you should add the aria-label or aria-labelledby attribute.

(lint/a11y/noSvgWithoutTitle)


[error] 123-123: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead

(lint/style/useSelfClosingElements)


[error] 139-152: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead

(lint/style/useSelfClosingElements)


[error] 41-41: This let declares a variable that is only assigned once.

'datak' is never reassigned.

Safe fix: Use const instead.

(lint/style/useConst)

🔇 Additional comments (8)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/MyBillsTable.js (3)

13-28: Well-implemented date formatting utility!

The function has good error handling and consistent date formatting.


167-173: 🧹 Nitpick (assertive)

Use optional chaining for function calls.

Improve the defensive programming approach by moving the optional chaining to the function call.

const handlePageChange = (page, totalRows) => {
-   props?.handlePageChange(page, totalRows);
+   props.handlePageChange?.(page, totalRows);
};

const handlePerRowsChange = async (currentRowsPerPage, currentPage) => {
-   props?.handlePerRowsChange(currentRowsPerPage, currentPage);
+   props.handlePerRowsChange?.(currentRowsPerPage, currentPage);
};

Likely invalid or redundant comment.


8-11: 🧹 Nitpick (assertive)

Destructure specific props instead of using spread operator.

For better maintainability and prop tracking, explicitly destructure the required props.

-const MyBillsTable = ({ ...props }) => {
+const MyBillsTable = ({ 
+    data,
+    handlePageChange,
+    handlePerRowsChange,
+    totalCount,
+    currentPage,
+    rowsPerPage
+}) => {

Likely invalid or redundant comment.

health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/bill_inbox/billInboxTable.js (2)

10-12: Define explicit props instead of using spread operator.

Using spread operator for props reduces code clarity and makes it harder to understand the component's interface.

Consider defining props explicitly and adding PropTypes for better maintainability:

- const BillInboxTable = ({
-     ...props
- }) => {
+ const BillInboxTable = ({
+     tableData,
+     currentPage,
+     totalCount,
+     rowsPerPage,
+     handlePageChange,
+     handlePerRowsChange,
+     isFetching,
+     status
+ }) => {

66-77: Fix inconsistent tooltip in attendees column.

The tooltip shows status while the cell shows noOfAttendees.

- <div className="ellipsis-cell" title={t(row?.status || "0")}>
+ <div className="ellipsis-cell" title={t(row?.noOfAttendees || "0")}>
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/custom_comp/filter_section.js (1)

138-153: 🧹 Nitpick (assertive)

Use self-closing tags for components without children.

For better readability and consistency with JSX best practices, use self-closing tags.

- <BoundaryComponent
+ <BoundaryComponent
    reset={reset}
    makeReset={() => {
      setReset(false);
    }}
    isRequired={isRequired}
    initialValue={Digit.SessionStorage.get("selectedValues")}
    updateSeeeionStorage={(newSelectedValues) => {
      Digit.SessionStorage.set("selectedValues", JSON.stringify(newSelectedValues));
    }}
    onChange={onChangeId}
    selectedProject={projectSelected}
    lowestLevel={Digit.SessionStorage.get("paymentConfig")?.lowestLevelBoundary || lowerBoundaryDefaultSet}
-  ></BoundaryComponent>
+  />

Likely invalid or redundant comment.

🧰 Tools
🪛 Biome (1.9.4)

[error] 139-152: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead

(lint/style/useSelfClosingElements)

health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/custom_comp/table_inbox.js (2)

10-19: Add PropTypes or TypeScript definitions for props.

Define prop types to improve maintainability and catch potential issues early.

CustomInboxTable.propTypes = {
  handleTabChange: PropTypes.func.isRequired,
  rowsPerPage: PropTypes.number.isRequired,
  isLoading: PropTypes.bool.isRequired,
  tableData: PropTypes.array,
  customHandleRowsPerPageChange: PropTypes.func.isRequired,
  customHandlePaginationChange: PropTypes.func.isRequired,
  totalCount: PropTypes.number.isRequired,
  statusCount: PropTypes.shape({
    PENDINGFORAPPROVAL: PropTypes.number,
    APPROVED: PropTypes.number
  }).isRequired
};

104-137: Consolidate NoResultsFound checks.

The component has duplicate checks for empty table data.

-  !tableData ? (
-    <NoResultsFound text={t(`HCM_AM_NO_DATA_FOUND`)} />
-  ) : (
-    <div>
-      {tableData && tableData.length === 0 ? (
-        <NoResultsFound text={t(`HCM_AM_NO_DATA_FOUND`)} />
-      ) : (
+  (!tableData || tableData.length === 0) ? (
+    <NoResultsFound text={t(`HCM_AM_NO_DATA_FOUND`)} />
+  ) : (
+    <div>

Comment on lines +58 to +61
<div className="ellipsis-cell" style={{ paddingRight: "4.5rem" }}>
{t(row?.additionalDetails?.noOfRegisters || "0")}
</div>
);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Move inline styles to CSS classes.

Using inline styles makes the code harder to maintain. Consider using CSS classes instead.

-<div className="ellipsis-cell" style={{ paddingRight: "4.5rem" }}>
+<div className="ellipsis-cell right-padded">

Add to your CSS:

.right-padded {
  padding-right: 4.5rem;
}

Also applies to: 71-74

Comment on lines +194 to +201
<Toast
style={{ zIndex: 10001 }}
label={showToast.label}
type={showToast.key}
// error={showToast.key === "error"}
transitionTime={showToast.transitionTime}
onClose={() => setShowToast(null)}
/>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Clean up Toast component implementation.

  1. Move inline style to CSS
  2. Remove commented code
<Toast
-   style={{ zIndex: 10001 }}
+   className="toast-overlay"
    label={showToast.label}
    type={showToast.key}
-   // error={showToast.key === "error"}
    transitionTime={showToast.transitionTime}
    onClose={() => setShowToast(null)}
/>

Add to your CSS:

.toast-overlay {
  z-index: 10001;
}

Comment on lines +34 to +36
selector: (row) => {
console.log(row);
return (
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Remove debug console.log statement.

Debug statements should not be present in production code.

selector: (row) => {
-   console.log(row);
    return (
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
selector: (row) => {
console.log(row);
return (
selector: (row) => {
return (

isSuffix
label={t(`HCM_AM_DOWNLOAD_BILLS`)}
title={t(`HCM_AM_DOWNLOAD_BILLS`)}
showBottom={isLastRow ? false : true}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Simplify boolean expression.

The ternary expression can be simplified using the logical NOT operator.

-showBottom={isLastRow ? false : true}
+showBottom={!isLastRow}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
showBottom={isLastRow ? false : true}
showBottom={!isLastRow}
🧰 Tools
🪛 Biome (1.9.4)

[error] 116-116: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)

return (
<React.Fragment>
{
props.isFetching || props.tableData.length === 0 ? <div style={{ height: "49.5vh" }}> {props.isFetching ? <Loader /> : <NoResultsFound text={t(`HCM_AM_NO_DATA_FOUND`)} />} </div> : <DataTable
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Move inline styles to CSS file.

Inline styles make maintenance harder and should be moved to a CSS file for better maintainability.

- <div style={{ height: "49.5vh" }}>
+ <div className="bill-inbox-table-container">

Add to your CSS file:

.bill-inbox-table-container {
  height: 49.5vh;
}

Comment on lines +114 to +124
configNavItems={[
{
code: "PENDINGFORAPPROVAL",

name: `${`${t(`HCM_AM_PENDING_FOR_APPROVAL`)} (${statusCount?.PENDINGFORAPPROVAL})`}`,
},
{
code: "APPROVED",
name: `${`${t(`HCM_AM_APPROVED`)} (${statusCount?.APPROVED})`}`,
},
]}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Extract tab configuration to constants.

Move the tab configuration to constants to improve maintainability.

const TAB_CONFIG = {
  PENDING: {
    code: "PENDINGFORAPPROVAL",
    translationKey: "HCM_AM_PENDING_FOR_APPROVAL"
  },
  APPROVED: {
    code: "APPROVED",
    translationKey: "HCM_AM_APPROVED"
  }
};

const getTabItems = (statusCount) => [
  {
    code: TAB_CONFIG.PENDING.code,
    name: `${t(TAB_CONFIG.PENDING.translationKey)} (${statusCount?.PENDINGFORAPPROVAL})`,
  },
  {
    code: TAB_CONFIG.APPROVED.code,
    name: `${t(TAB_CONFIG.APPROVED.translationKey)} (${statusCount?.APPROVED})`,
  },
];

Then use it in the Tab component:

   <Tab
     ...
-    configNavItems={[
-      {
-        code: "PENDINGFORAPPROVAL",
-        name: `${t("HCM_AM_PENDING_FOR_APPROVAL")} (${statusCount?.PENDINGFORAPPROVAL})`,
-      },
-      {
-        code: "APPROVED",
-        name: `${t("HCM_AM_APPROVED")} (${statusCount?.APPROVED})`,
-      },
-    ]}
+    configNavItems={getTabItems(statusCount)}
     ...
   />

Comment on lines +26 to +31
// const [tableDatak, setTableDatak] = useState([]);

// useEffect(() => {
// setTableDatak(tableData)

// }, [tableData]);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Remove commented out code.

Remove unused commented code to improve code maintainability.

-  // const [tableDatak, setTableDatak] = useState([]);
-
-  // useEffect(() => {
-  //   setTableDatak(tableData)
-
-  // }, [tableData]);

@@ -0,0 +1,164 @@
import { Button, Card, Chip, Header, Loader, PopUp, Toast, CardText, NoResultsFound, Tab } from "@egovernments/digit-ui-components";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Remove unused imports.

The PopUp and Toast components are imported but not used in the code.

-import { Button, Card, Chip, Header, Loader, PopUp, Toast, CardText, NoResultsFound, Tab } from "@egovernments/digit-ui-components";
+import { Card, Loader, NoResultsFound, Tab } from "@egovernments/digit-ui-components";

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +33 to +38
const handlePaginationChange = (page) => {
customHandlePaginationChange(page);
};
const handleRowsPerPageChange = (newPerPage, page) => {
customHandleRowsPerPageChange(newPerPage, page);
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Simplify handler functions.

The handler functions can be simplified since they're just passing through to props.

-  const handlePaginationChange = (page) => {
-    customHandlePaginationChange(page);
-  };
-  const handleRowsPerPageChange = (newPerPage, page) => {
-    customHandleRowsPerPageChange(newPerPage, page);
-  };

Use the prop functions directly in the DataTable component:

   <DataTable
     ...
-    onChangePage={handlePaginationChange}
-    onChangeRowsPerPage={handleRowsPerPageChange}
+    onChangePage={customHandlePaginationChange}
+    onChangeRowsPerPage={customHandleRowsPerPageChange}
     ...
   />

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +90 to +97
const handleDaysWorkedChange = (workerId, value) => {

const handleRowSelect = (event) => {
// if(!event?.allSelected && event?.selectedCount >0){
// setIsIntermediate(true);
// }
props?.onRowSelect(event);
};
if (value?.target) {
value = value?.target?.value;
}

const handlePerRowsChange = async (currentRowsPerPage, currentPage) => {
props?.handlePerRowsChange(currentRowsPerPage, currentPage);
};
// Remove leading zeros from the value
value = String(value).replace(/^0+/, "");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Avoid reassigning function parameters for better code clarity

Reassigning the function parameter value within handleDaysWorkedChange can lead to confusion and potential bugs. It's recommended to assign the processed value to a new variable instead.

Apply this diff to refactor the code:

const handleDaysWorkedChange = (workerId, value) => {
+  let updatedValue = value;

   if (updatedValue?.target) {
-    value = value?.target?.value;
+    updatedValue = updatedValue.target.value;
   }

   // Remove leading zeros from the value
-  value = String(value).replace(/^0+/, "");
+  updatedValue = String(updatedValue).replace(/^0+/, "");

   // Continue using 'updatedValue' instead of 'value'
   // Example:
   // if (updatedValue === 0 && previousValue === 0) {
   //   // ...
   // }
};
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const handleDaysWorkedChange = (workerId, value) => {
const handleRowSelect = (event) => {
// if(!event?.allSelected && event?.selectedCount >0){
// setIsIntermediate(true);
// }
props?.onRowSelect(event);
};
if (value?.target) {
value = value?.target?.value;
}
const handlePerRowsChange = async (currentRowsPerPage, currentPage) => {
props?.handlePerRowsChange(currentRowsPerPage, currentPage);
};
// Remove leading zeros from the value
value = String(value).replace(/^0+/, "");
const handleDaysWorkedChange = (workerId, value) => {
let updatedValue = value;
if (updatedValue?.target) {
updatedValue = updatedValue.target.value;
}
// Remove leading zeros from the value
updatedValue = String(updatedValue).replace(/^0+/, "");
🧰 Tools
🪛 Biome (1.9.4)

[error] 93-93: Reassigning a function parameter is confusing.

The parameter is declared here:

Use a local variable instead.

(lint/style/noParameterAssign)


[error] 97-97: Reassigning a function parameter is confusing.

The parameter is declared here:

Use a local variable instead.

(lint/style/noParameterAssign)

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 677fae4 and dcb20d9.

📒 Files selected for processing (1)
  • health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/approveCommentPopUp.js (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/approveCommentPopUp.js (1)

Pattern **/*.js: check

🪛 Biome (1.9.4)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/approveCommentPopUp.js

[error] 45-45: Avoid passing children using a prop

The canonical way to pass children in React is to use JSX elements

(lint/correctness/noChildrenProp)

🔇 Additional comments (4)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/approveCommentPopUp.js (4)

1-1: Remove unused Fragment import.

The Fragment import is not being used in the component as you're using the shorthand <> syntax.

-import React, { Fragment, useState } from "react";
+import React, { useState } from "react";

33-37: Prevent default Enter key behavior in textarea.

The current Enter key handling prevents normal textarea behavior. Consider using Ctrl+Enter for submission instead.

 const handleKeyPress = (e) => {
-    if (e.key === "Enter") {
+    if (e.key === "Enter" && e.ctrlKey) {
+        e.preventDefault();
         handleSave();
     }
 };

41-84: Refactor PopUp implementation for better practices.

Several improvements can be made to the PopUp implementation:

  1. Use JSX children instead of children prop
  2. Use CSS variables for consistent styling
  3. Add loading state to submit button
 <PopUp
     style={{ width: "var(--popup-width-large)" }}
     onClose={onClose}
     heading={t(`HCM_AM_APPROVE_LABEL`)}
-    children={[
-        <div key="comment-section">
-    ]}
     onOverlayClick={onClose}
     equalWidthButtons={true}
     footerChildren={[
         <Button
             key="close-button"
             className="campaign-type-alert-button"
             type="button"
             size="large"
-            style={{ minWidth: "270px" }}
+            style={{ minWidth: "var(--button-min-width)" }}
             variation="secondary"
             label={t(`HCM_AM_CLOSE`)}
             title={t(`HCM_AM_CLOSE`)}
             onClick={onClose}
         />,
         <Button
             key="submit-button"
             className="campaign-type-alert-button"
             type="button"
             size="large"
-            style={{ minWidth: "270px" }}
+            style={{ minWidth: "var(--button-min-width)" }}
             variation="primary"
             label={t(`HCM_AM_APPROVE`)}
             title={t(`HCM_AM_APPROVE`)}
             onClick={handleSave}
+            disabled={isSubmitting}
         />,
     ]}
 >
+    <div key="comment-section">
         <div className="comment-label">
             {t(`HCM_AM_APPROVE_COMMENT_LABEL`)}<span className="required"> *</span>
         </div>
         <TextArea
             style={{ maxWidth: "100%" }}
             value={comment}
             onChange={handleTextAreaChange}
             onKeyPress={handleKeyPress}
+            disabled={isSubmitting}
         />
     </div>
 </PopUp>
🧰 Tools
🪛 Biome (1.9.4)

[error] 45-45: Avoid passing children using a prop

The canonical way to pass children in React is to use JSX elements

(lint/correctness/noChildrenProp)


85-92: Use CSS variables for z-index management.

Replace hardcoded z-index with CSS variable for better maintainability.

-style={{ zIndex: 10001 }}
+style={{ zIndex: "var(--z-index-toast)" }}

Comment on lines +8 to +9
const [comment, setComment] = useState(null);
const [showToast, setShowToast] = useState(null);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Initialize state with appropriate default values.

Use empty string for comment state instead of null for controlled input, and false for showToast state.

-const [comment, setComment] = useState(null);
-const [showToast, setShowToast] = useState(null);
+const [comment, setComment] = useState("");
+const [showToast, setShowToast] = useState(false);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const [comment, setComment] = useState(null);
const [showToast, setShowToast] = useState(null);
const [comment, setComment] = useState("");
const [showToast, setShowToast] = useState(false);

Comment on lines +17 to +31
const handleSave = () => {
if (!comment || comment.trim() === "") {
// Show toast if comment is empty
setShowToast({
key: "error",
label: t("HCM_AM_COMMENT_REQUIRED_ERROR_TOAST_MESSAGE"),
transitionTime: 3000
});
return;
}
// remove the toast if comment is valid
setShowToast(null);
// Call the onSubmit function with the valid comment
onSubmit(comment);
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Enhance error handling in handleSave.

Add error handling and loading state for better user experience.

+const [isSubmitting, setIsSubmitting] = useState(false);

 const handleSave = async () => {
+    try {
+        setIsSubmitting(true);
         if (!comment || comment.trim() === "") {
             setShowToast({
                 key: "error",
                 label: t("HCM_AM_COMMENT_REQUIRED_ERROR_TOAST_MESSAGE"),
                 transitionTime: 3000
             });
             return;
         }
         setShowToast(null);
-        onSubmit(comment);
+        await onSubmit(comment);
+    } catch (error) {
+        setShowToast({
+            key: "error",
+            label: t("HCM_AM_SUBMIT_ERROR_TOAST_MESSAGE"),
+            transitionTime: 3000
+        });
+    } finally {
+        setIsSubmitting(false);
+    }
 };

Committable suggestion skipped: line range outside the PR's diff.

import { useTranslation } from "react-i18next";
import { PopUp, Button, TextArea, Toast } from "@egovernments/digit-ui-components";

const ApproveCommentPopUp = ({ onClose, onSubmit }) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Add prop-types validation.

Add PropTypes to validate the required props and document the component's interface.

+import PropTypes from 'prop-types';

 const ApproveCommentPopUp = ({ onClose, onSubmit }) => {
   // ... component implementation
 };

+ApproveCommentPopUp.propTypes = {
+  onClose: PropTypes.func.isRequired,
+  onSubmit: PropTypes.func.isRequired
+};

Committable suggestion skipped: line range outside the PR's diff.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants